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:
karlklose@chromium.org 2011-03-21 09:59:58 +00:00
parent b604befe61
commit e820926108
4 changed files with 100 additions and 28 deletions

View File

@ -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++) {

View File

@ -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;

View File

@ -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,12 +997,16 @@ void Decoder::DecodeType3(Instruction* instr) {
void Decoder::DecodeType4(Instruction* instr) {
ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
if (instr->Bit(22) != 0) {
// Privileged mode currently not supported.
Unknown(instr);
} else {
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);
}

View File

@ -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,12 +421,24 @@ void ArmDebugger::Debug() {
cur = reinterpret_cast<byte*>(sim_->get_pc());
end = cur + (10 * Instruction::kInstrSize);
} else if (argc == 2) {
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;
int32_t value2;
@ -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");