// executed in the simulator. Since the host is typically IA32 we will not
// get the correct MIPS-like behaviour on unaligned accesses.
+void Simulator::TraceRegWr(int32_t value) {
+ if (::v8::internal::FLAG_trace_sim) {
+ SNPrintF(trace_buf_, "%08x", value);
+ }
+}
+
+
+// TODO(plind): consider making icount_ printing a flag option.
+void Simulator::TraceMemRd(int32_t addr, int32_t value) {
+ if (::v8::internal::FLAG_trace_sim) {
+ SNPrintF(trace_buf_, "%08x <-- [%08x] (%d)", value, addr, icount_);
+ }
+}
+
+
+void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) {
+ if (::v8::internal::FLAG_trace_sim) {
+ switch (t) {
+ case BYTE:
+ SNPrintF(trace_buf_, " %02x --> [%08x]",
+ static_cast<int8_t>(value), addr);
+ break;
+ case HALF:
+ SNPrintF(trace_buf_, " %04x --> [%08x]", static_cast<int16_t>(value),
+ addr);
+ break;
+ case WORD:
+ SNPrintF(trace_buf_, "%08x --> [%08x]", value, addr);
+ break;
+ }
+ }
+}
+
+
int Simulator::ReadW(int32_t addr, Instruction* instr) {
if (addr >=0 && addr < 0x400) {
// This has to be a NULL-dereference, drop into debugger.
}
if ((addr & kPointerAlignmentMask) == 0) {
intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+ TraceMemRd(addr, static_cast<int32_t>(*ptr));
return *ptr;
}
PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
}
if ((addr & kPointerAlignmentMask) == 0) {
intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+ TraceMemWr(addr, value, WORD);
*ptr = value;
return;
}
uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
if ((addr & 1) == 0) {
uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+ TraceMemRd(addr, static_cast<int32_t>(*ptr));
return *ptr;
}
PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
if ((addr & 1) == 0) {
int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+ TraceMemRd(addr, static_cast<int32_t>(*ptr));
return *ptr;
}
PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
if ((addr & 1) == 0) {
uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+ TraceMemWr(addr, value, HALF);
*ptr = value;
return;
}
void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
if ((addr & 1) == 0) {
int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+ TraceMemWr(addr, value, HALF);
*ptr = value;
return;
}
uint32_t Simulator::ReadBU(int32_t addr) {
uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
+ TraceMemRd(addr, static_cast<int32_t>(*ptr));
return *ptr & 0xff;
}
int32_t Simulator::ReadB(int32_t addr) {
int8_t* ptr = reinterpret_cast<int8_t*>(addr);
+ TraceMemRd(addr, static_cast<int32_t>(*ptr));
return *ptr;
}
void Simulator::WriteB(int32_t addr, uint8_t value) {
uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
+ TraceMemWr(addr, value, BYTE);
*ptr = value;
}
void Simulator::WriteB(int32_t addr, int8_t value) {
int8_t* ptr = reinterpret_cast<int8_t*>(addr);
+ TraceMemWr(addr, value, BYTE);
*ptr = value;
}
break;
// Conditional moves.
case MOVN:
- if (rt) set_register(rd_reg, rs);
+ if (rt) {
+ set_register(rd_reg, rs);
+ TraceRegWr(rs);
+ }
break;
case MOVCI: {
uint32_t cc = instr->FBccValue();
break;
}
case MOVZ:
- if (!rt) set_register(rd_reg, rs);
+ if (!rt) {
+ set_register(rd_reg, rs);
+ TraceRegWr(rs);
+ }
break;
default: // For other special opcodes we do the default operation.
set_register(rd_reg, alu_out);
+ TraceRegWr(alu_out);
}
}
switch (instr->FunctionFieldRaw()) {
case MUL:
set_register(rd_reg, alu_out);
+ TraceRegWr(alu_out);
// HI and LO are UNPREDICTABLE after the operation.
set_register(LO, Unpredictable);
set_register(HI, Unpredictable);
break;
default: // For other special2 opcodes we do the default operation.
set_register(rd_reg, alu_out);
+ TraceRegWr(alu_out);
}
}
case INS:
// Ins instr leaves result in Rt, rather than Rd.
set_register(rt_reg, alu_out);
+ TraceRegWr(alu_out);
break;
case EXT:
set_register(rt_reg, alu_out);
+ TraceRegWr(alu_out);
break;
case BSHFL:
set_register(rd_reg, alu_out);
+ TraceRegWr(alu_out);
break;
default:
UNREACHABLE();
case XORI:
case LUI:
set_register(rt_reg, alu_out);
+ TraceRegWr(alu_out);
break;
// ------------- Memory instructions.
case LB:
CheckICache(isolate_->simulator_i_cache(), instr);
}
pc_modified_ = false;
+ v8::internal::EmbeddedVector<char, 256> buffer;
if (::v8::internal::FLAG_trace_sim) {
+ SNPrintF(trace_buf_, "%s", "");
disasm::NameConverter converter;
disasm::Disassembler dasm(converter);
- // Use a reasonably large buffer.
- v8::internal::EmbeddedVector<char, 256> buffer;
dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
- PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
- buffer.start());
}
switch (instr->InstructionType()) {
default:
UNSUPPORTED();
}
+ if (::v8::internal::FLAG_trace_sim) {
+ PrintF(" 0x%08x %-44s %s\n", reinterpret_cast<intptr_t>(instr),
+ buffer.start(), trace_buf_.start());
+ }
if (!pc_modified_) {
set_register(pc, reinterpret_cast<int32_t>(instr) +
Instruction::kInstrSize);