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");
|
RecordComment("[ Constant Pool");
|
||||||
|
|
||||||
// Put down constant pool marker "Undefined instruction" as specified by
|
// Put down constant pool marker "Undefined instruction" as specified by
|
||||||
// A3.1 Instruction set encoding.
|
// A5.6 (ARMv7) Instruction set encoding.
|
||||||
emit(0x03000000 | num_prinfo_);
|
emit(kConstantPoolMarker | num_prinfo_);
|
||||||
|
|
||||||
// Emit constant pool entries.
|
// Emit constant pool entries.
|
||||||
for (int i = 0; i < num_prinfo_; i++) {
|
for (int i = 0; i < num_prinfo_; i++) {
|
||||||
|
@ -89,6 +89,11 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
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.
|
// Number of registers in normal ARM mode.
|
||||||
static const int kNumRegisters = 16;
|
static const int kNumRegisters = 16;
|
||||||
|
|
||||||
|
@ -89,6 +89,9 @@ class Decoder {
|
|||||||
// Returns the length of the disassembled machine instruction in bytes.
|
// Returns the length of the disassembled machine instruction in bytes.
|
||||||
int InstructionDecode(byte* instruction);
|
int InstructionDecode(byte* instruction);
|
||||||
|
|
||||||
|
static bool IsConstantPoolAt(byte* instr_ptr);
|
||||||
|
static int ConstantPoolSizeAt(byte* instr_ptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Bottleneck functions to print into the out_buffer.
|
// Bottleneck functions to print into the out_buffer.
|
||||||
void PrintChar(const char ch);
|
void PrintChar(const char ch);
|
||||||
@ -899,6 +902,7 @@ void Decoder::DecodeType2(Instruction* instr) {
|
|||||||
case da_x: {
|
case da_x: {
|
||||||
if (instr->HasW()) {
|
if (instr->HasW()) {
|
||||||
Unknown(instr); // not used in V8
|
Unknown(instr); // not used in V8
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
|
Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
|
||||||
break;
|
break;
|
||||||
@ -906,6 +910,7 @@ void Decoder::DecodeType2(Instruction* instr) {
|
|||||||
case ia_x: {
|
case ia_x: {
|
||||||
if (instr->HasW()) {
|
if (instr->HasW()) {
|
||||||
Unknown(instr); // not used in V8
|
Unknown(instr); // not used in V8
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
|
Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
|
||||||
break;
|
break;
|
||||||
@ -992,11 +997,15 @@ void Decoder::DecodeType3(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeType4(Instruction* instr) {
|
void Decoder::DecodeType4(Instruction* instr) {
|
||||||
ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
|
if (instr->Bit(22) != 0) {
|
||||||
if (instr->HasL()) {
|
// Privileged mode currently not supported.
|
||||||
Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
|
Unknown(instr);
|
||||||
} else {
|
} 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
|
// vmov: Rt = Sn
|
||||||
// vcvt: Dd = Sm
|
// vcvt: Dd = Sm
|
||||||
// vcvt: Sd = Dm
|
// vcvt: Sd = Dm
|
||||||
|
// Dd = vabs(Dm)
|
||||||
|
// Dd = vneg(Dm)
|
||||||
// Dd = vadd(Dn, Dm)
|
// Dd = vadd(Dn, Dm)
|
||||||
// Dd = vsub(Dn, Dm)
|
// Dd = vsub(Dn, Dm)
|
||||||
// Dd = vmul(Dn, Dm)
|
// Dd = vmul(Dn, Dm)
|
||||||
@ -1297,7 +1308,23 @@ void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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 ",
|
"%08x ",
|
||||||
instr->InstructionBits());
|
instr->InstructionBits());
|
||||||
if (instr->ConditionField() == kSpecialCondition) {
|
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;
|
return Instruction::kInstrSize;
|
||||||
}
|
}
|
||||||
switch (instr->TypeValue()) {
|
switch (instr->TypeValue()) {
|
||||||
@ -1413,12 +1448,7 @@ int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
|
|||||||
|
|
||||||
|
|
||||||
int Disassembler::ConstantPoolSizeAt(byte* instruction) {
|
int Disassembler::ConstantPoolSizeAt(byte* instruction) {
|
||||||
int instruction_bits = *(reinterpret_cast<int*>(instruction));
|
return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
|
||||||
if ((instruction_bits & 0xfff00000) == 0x03000000) {
|
|
||||||
return instruction_bits & 0x0000ffff;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,16 +316,26 @@ void ArmDebugger::Debug() {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
|
for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
|
||||||
dvalue = GetVFPDoubleRegisterValue(i);
|
dvalue = GetVFPDoubleRegisterValue(i);
|
||||||
PrintF("%3s: %f\n",
|
uint64_t as_words = BitCast<uint64_t>(dvalue);
|
||||||
VFPRegisters::Name(i, true), 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 {
|
} else {
|
||||||
if (GetValue(arg1, &value)) {
|
if (GetValue(arg1, &value)) {
|
||||||
PrintF("%s: 0x%08x %d \n", arg1, value, value);
|
PrintF("%s: 0x%08x %d \n", arg1, value, value);
|
||||||
} else if (GetVFPSingleValue(arg1, &svalue)) {
|
} 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)) {
|
} 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 {
|
} else {
|
||||||
PrintF("%s unrecognized\n", arg1);
|
PrintF("%s unrecognized\n", arg1);
|
||||||
}
|
}
|
||||||
@ -380,11 +390,24 @@ void ArmDebugger::Debug() {
|
|||||||
end = cur + words;
|
end = cur + words;
|
||||||
|
|
||||||
while (cur < end) {
|
while (cur < end) {
|
||||||
PrintF(" 0x%08x: 0x%08x %10d\n",
|
PrintF(" 0x%08x: 0x%08x %10d",
|
||||||
reinterpret_cast<intptr_t>(cur), *cur, *cur);
|
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++;
|
cur++;
|
||||||
}
|
}
|
||||||
} else if (strcmp(cmd, "disasm") == 0) {
|
} else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
|
||||||
disasm::NameConverter converter;
|
disasm::NameConverter converter;
|
||||||
disasm::Disassembler dasm(converter);
|
disasm::Disassembler dasm(converter);
|
||||||
// use a reasonably large buffer
|
// use a reasonably large buffer
|
||||||
@ -398,11 +421,23 @@ void ArmDebugger::Debug() {
|
|||||||
cur = reinterpret_cast<byte*>(sim_->get_pc());
|
cur = reinterpret_cast<byte*>(sim_->get_pc());
|
||||||
end = cur + (10 * Instruction::kInstrSize);
|
end = cur + (10 * Instruction::kInstrSize);
|
||||||
} else if (argc == 2) {
|
} else if (argc == 2) {
|
||||||
int32_t value;
|
int regnum = Registers::Number(arg1);
|
||||||
if (GetValue(arg1, &value)) {
|
if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
|
||||||
cur = reinterpret_cast<byte*>(sim_->get_pc());
|
// The argument is an address or a register name.
|
||||||
// Disassemble <arg1> instructions.
|
int32_t value;
|
||||||
end = cur + (value * Instruction::kInstrSize);
|
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 {
|
} else {
|
||||||
int32_t value1;
|
int32_t value1;
|
||||||
@ -524,8 +559,10 @@ void ArmDebugger::Debug() {
|
|||||||
PrintF("mem <address> [<words>]\n");
|
PrintF("mem <address> [<words>]\n");
|
||||||
PrintF(" dump memory content, default dump 10 words)\n");
|
PrintF(" dump memory content, default dump 10 words)\n");
|
||||||
PrintF("disasm [<instructions>]\n");
|
PrintF("disasm [<instructions>]\n");
|
||||||
PrintF("disasm [[<address>] <instructions>]\n");
|
PrintF("disasm [<address/register>]\n");
|
||||||
PrintF(" disassemble code, default is 10 instructions from pc\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("gdb\n");
|
||||||
PrintF(" enter gdb\n");
|
PrintF(" enter gdb\n");
|
||||||
PrintF("break <address>\n");
|
PrintF("break <address>\n");
|
||||||
@ -543,7 +580,7 @@ void ArmDebugger::Debug() {
|
|||||||
PrintF(" The first %d stop codes are watched:\n",
|
PrintF(" The first %d stop codes are watched:\n",
|
||||||
Simulator::kNumOfWatchedStops);
|
Simulator::kNumOfWatchedStops);
|
||||||
PrintF(" - They can be enabled / disabled: the Simulator\n");
|
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(" - The Simulator keeps track of how many times they \n");
|
||||||
PrintF(" are met. (See the info command.) Going over a\n");
|
PrintF(" are met. (See the info command.) Going over a\n");
|
||||||
PrintF(" disabled stop still increases its counter. \n");
|
PrintF(" disabled stop still increases its counter. \n");
|
||||||
|
Loading…
Reference in New Issue
Block a user