Mostly complete tracing. Probably a lot of bugs.

This commit is contained in:
Ben Vanik
2014-08-14 20:28:44 -07:00
parent cebf595958
commit c275562594
54 changed files with 1052 additions and 161 deletions

View File

@@ -13,55 +13,28 @@
#include <alloy/core.h>
#include <alloy/vec128.h>
namespace alloy { namespace runtime {
class Runtime;
class ThreadState;
} }
namespace alloy {
namespace frontend {
namespace ppc {
using vec128_t = alloy::vec128_t;
typedef union {
uint32_t value;
struct {
uint8_t lt :1; // Negative (LT) - result is negative
uint8_t gt :1; // Positive (GT) - result is positive (and not zero)
uint8_t eq :1; // Zero (EQ) - result is zero or a stwcx/stdcx completed successfully
uint8_t so :1; // Summary Overflow (SO) - copy of XER[SO]
} cr0;
struct {
uint8_t fx :1; // FP exception summary - copy of FPSCR[FX]
uint8_t fex :1; // FP enabled exception summary - copy of FPSCR[FEX]
uint8_t vx :1; // FP invalid operation exception summary - copy of FPSCR[VX]
uint8_t ox :1; // FP overflow exception - copy of FPSCR[OX]
} cr1;
struct {
uint8_t value :4;
} cr2;
struct {
uint8_t value :4;
} cr3;
struct {
uint8_t value :4;
} cr4;
struct {
uint8_t value :4;
} cr5;
struct {
uint8_t value :4;
} cr6;
struct {
uint8_t value :4;
} cr7;
} PPCCR;
// Map:
// 0-31: GPR
// 32-63: FPR
// 64: LR
// 65: CTR
// 66: XER
// 67: FPSCR
// 68: VSCR
// 69-76: CR0-7
// 100: invalid
// 128-256: VR
#pragma pack(push, 4)
typedef struct XECACHEALIGN64 PPCContext_s {
@@ -194,12 +167,15 @@ typedef struct XECACHEALIGN64 PPCContext_s {
// fpscr.value = (fpscr.value & ~0x000F8000) | v;
// }
// Thread ID assigned to this context.
uint32_t thread_id;
// Reserve address for load acquire/store release. Shared.
uint32_t* reserve_address;
uint32_t* reserve_address;
// Runtime-specific data pointer. Used on callbacks to get access to the
// current runtime and its data.
runtime::Runtime* runtime;
runtime::Runtime* runtime;
void SetRegFromString(const char* name, const char* value);
bool CompareRegWithString(const char* name, const char* value,
@@ -207,10 +183,8 @@ typedef struct XECACHEALIGN64 PPCContext_s {
} PPCContext;
#pragma pack(pop)
} // namespace ppc
} // namespace frontend
} // namespace alloy
#endif // ALLOY_FRONTEND_PPC_PPC_CONTEXT_H_

View File

@@ -297,8 +297,8 @@ XEEMITTER(fnmsubsx, 0xEC00003C, A)(PPCHIRBuilder& f, InstrData& i) {
XEEMITTER(fcfidx, 0xFC00069C, X)(PPCHIRBuilder& f, InstrData& i) {
// frD <- signed_int64_to_double( frB )
Value* v = f.Convert(f.Cast(f.LoadFPR(i.A.FRB), INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
Value* v = f.Convert(f.Cast(f.LoadFPR(i.X.RB), INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
@@ -337,7 +337,7 @@ XEEMITTER(fctiwx, 0xFC00001C, X)(PPCHIRBuilder& f, InstrData& i) {
v = f.Cast(f.ZeroExtend(v, INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
@@ -409,7 +409,8 @@ XEEMITTER(mffsx, 0xFC00048E, X)(PPCHIRBuilder& f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.StoreFPR(i.X.RT, f.Cast(f.LoadFPSCR(), FLOAT64_TYPE));
Value* v = f.Cast(f.LoadFPSCR(), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
return 0;
}

View File

@@ -47,7 +47,8 @@ PPCFrontend::PPCFrontend(Runtime* runtime) : Frontend(runtime) {
InitializeIfNeeded();
std::unique_ptr<ContextInfo> context_info(
new ContextInfo(sizeof(PPCContext), offsetof(PPCContext, thread_state)));
new ContextInfo(sizeof(PPCContext), offsetof(PPCContext, thread_state),
offsetof(PPCContext, thread_id)));
// Add fields/etc.
context_info_ = std::move(context_info);
}
@@ -77,10 +78,11 @@ int PPCFrontend::DeclareFunction(FunctionInfo* symbol_info) {
int PPCFrontend::DefineFunction(FunctionInfo* symbol_info,
uint32_t debug_info_flags,
uint32_t trace_flags,
Function** out_function) {
PPCTranslator* translator = translator_pool_.Allocate(this);
int result =
translator->Translate(symbol_info, debug_info_flags, out_function);
translator->Translate(symbol_info, debug_info_flags, trace_flags, out_function);
translator_pool_.Release(translator);
return result;
}

View File

@@ -24,14 +24,14 @@ class PPCTranslator;
class PPCFrontend : public Frontend {
public:
PPCFrontend(runtime::Runtime* runtime);
virtual ~PPCFrontend();
~PPCFrontend() override;
virtual int Initialize();
int Initialize() override;
virtual int DeclareFunction(runtime::FunctionInfo* symbol_info);
virtual int DefineFunction(runtime::FunctionInfo* symbol_info,
uint32_t debug_info_flags,
runtime::Function** out_function);
int DeclareFunction(runtime::FunctionInfo* symbol_info) override;
int DefineFunction(runtime::FunctionInfo* symbol_info,
uint32_t debug_info_flags, uint32_t trace_flags,
runtime::Function** out_function) override;
private:
TypePool<PPCTranslator, PPCFrontend*> translator_pool_;

View File

@@ -43,7 +43,7 @@ void PPCHIRBuilder::Reset() {
HIRBuilder::Reset();
}
int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
SCOPE_profile_cpu_f("alloy");
Memory* memory = frontend_->memory();
@@ -53,7 +53,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
start_address_ = symbol_info->address();
instr_count_ = (symbol_info->end_address() - symbol_info->address()) / 4 + 1;
with_debug_info_ = with_debug_info;
with_debug_info_ = (flags & EMIT_DEBUG_COMMENTS) == EMIT_DEBUG_COMMENTS;
if (with_debug_info_) {
Comment("%s fn %.8X-%.8X %s", symbol_info->module()->name().c_str(),
symbol_info->address(), symbol_info->end_address(),
@@ -84,6 +84,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
i.code = poly::load_and_swap<uint32_t>(p + address);
// TODO(benvanik): find a way to avoid using the opcode tables.
i.type = GetInstrType(i.code);
trace_info_.dest_count = 0;
// Mark label, if we were assigned one earlier on in the walk.
// We may still get a label, but it'll be inserted by LookupLabel
@@ -136,6 +137,30 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
// DebugBreak();
// TraceInvalidInstruction(i);
}
if (flags & EMIT_TRACE_SOURCE) {
if (flags & EMIT_TRACE_SOURCE_VALUES) {
switch (trace_info_.dest_count) {
case 0:
TraceSource(i.address);
break;
case 1:
TraceSource(i.address, trace_info_.dests[0].reg,
trace_info_.dests[0].value);
break;
case 2:
TraceSource(i.address, trace_info_.dests[0].reg,
trace_info_.dests[0].value, trace_info_.dests[1].reg,
trace_info_.dests[1].value);
break;
default:
assert_unhandled_case(trace_info_.dest_count);
break;
}
} else {
TraceSource(i.address);
}
}
}
return Finalize();
@@ -205,6 +230,10 @@ Value* PPCHIRBuilder::LoadLR() {
void PPCHIRBuilder::StoreLR(Value* value) {
assert_true(value->type == INT64_TYPE);
StoreContext(offsetof(PPCContext, lr), value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = 64;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadCTR() {
@@ -214,6 +243,10 @@ Value* PPCHIRBuilder::LoadCTR() {
void PPCHIRBuilder::StoreCTR(Value* value) {
assert_true(value->type == INT64_TYPE);
StoreContext(offsetof(PPCContext, ctr), value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = 65;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadCR(uint32_t n) {
@@ -232,6 +265,8 @@ void PPCHIRBuilder::StoreCR(uint32_t n, Value* value) {
void PPCHIRBuilder::StoreCRField(uint32_t n, uint32_t bit, Value* value) {
StoreContext(offsetof(PPCContext, cr0) + (4 * n) + bit, value);
// TODO(benvanik): trace CR.
}
void PPCHIRBuilder::UpdateCR(uint32_t n, Value* lhs, bool is_signed) {
@@ -256,6 +291,8 @@ void PPCHIRBuilder::UpdateCR(uint32_t n, Value* lhs, Value* rhs,
// Value* so = AllocValue(UINT8_TYPE);
// StoreContext(offsetof(PPCContext, cr) + (4 * n) + 3, so);
// TOOD(benvanik): trace CR.
}
void PPCHIRBuilder::UpdateCR6(Value* src_value) {
@@ -265,6 +302,8 @@ void PPCHIRBuilder::UpdateCR6(Value* src_value) {
StoreContext(offsetof(PPCContext, cr6.cr6_all_equal),
IsFalse(Not(src_value)));
StoreContext(offsetof(PPCContext, cr6.cr6_none_equal), IsFalse(src_value));
// TOOD(benvanik): trace CR.
}
Value* PPCHIRBuilder::LoadFPSCR() {
@@ -274,6 +313,10 @@ Value* PPCHIRBuilder::LoadFPSCR() {
void PPCHIRBuilder::StoreFPSCR(Value* value) {
assert_true(value->type == INT64_TYPE);
StoreContext(offsetof(PPCContext, fpscr), value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = 67;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadXER() {
@@ -290,6 +333,10 @@ Value* PPCHIRBuilder::LoadCA() {
void PPCHIRBuilder::StoreCA(Value* value) {
assert_true(value->type == INT8_TYPE);
StoreContext(offsetof(PPCContext, xer_ca), value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = 66;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadSAT() {
@@ -299,6 +346,10 @@ Value* PPCHIRBuilder::LoadSAT() {
void PPCHIRBuilder::StoreSAT(Value* value) {
value = Truncate(value, INT8_TYPE);
StoreContext(offsetof(PPCContext, vscr_sat), value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = 44;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadGPR(uint32_t reg) {
@@ -308,6 +359,10 @@ Value* PPCHIRBuilder::LoadGPR(uint32_t reg) {
void PPCHIRBuilder::StoreGPR(uint32_t reg, Value* value) {
assert_true(value->type == INT64_TYPE);
StoreContext(offsetof(PPCContext, r) + reg * 8, value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = reg;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadFPR(uint32_t reg) {
@@ -317,6 +372,10 @@ Value* PPCHIRBuilder::LoadFPR(uint32_t reg) {
void PPCHIRBuilder::StoreFPR(uint32_t reg, Value* value) {
assert_true(value->type == FLOAT64_TYPE);
StoreContext(offsetof(PPCContext, f) + reg * 8, value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = reg + 32;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadVR(uint32_t reg) {
@@ -326,6 +385,10 @@ Value* PPCHIRBuilder::LoadVR(uint32_t reg) {
void PPCHIRBuilder::StoreVR(uint32_t reg, Value* value) {
assert_true(value->type == VEC128_TYPE);
StoreContext(offsetof(PPCContext, v) + reg * 16, value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
trace_reg.reg = 128 + reg;
trace_reg.value = value;
}
Value* PPCHIRBuilder::LoadAcquire(Value* address, TypeName type,

View File

@@ -33,7 +33,15 @@ class PPCHIRBuilder : public hir::HIRBuilder {
virtual void Reset();
int Emit(runtime::FunctionInfo* symbol_info, bool with_debug_info);
enum EmitFlags {
// Emit comment nodes.
EMIT_DEBUG_COMMENTS = 1 << 0,
// Emit TraceSource nodes.
EMIT_TRACE_SOURCE = 1 << 1,
// Emit TraceSource nodes with the resulting values of the operations.
EMIT_TRACE_SOURCE_VALUES = EMIT_TRACE_SOURCE | (1 << 2),
};
int Emit(runtime::FunctionInfo* symbol_info, uint32_t flags);
runtime::FunctionInfo* symbol_info() const { return symbol_info_; }
runtime::FunctionInfo* LookupFunction(uint64_t address);
@@ -89,6 +97,15 @@ class PPCHIRBuilder : public hir::HIRBuilder {
uint64_t instr_count_;
Instr** instr_offset_list_;
Label** label_list_;
// Reset each instruction.
struct {
uint32_t dest_count;
struct {
uint8_t reg;
Value* value;
} dests[4];
} trace_info_;
};
} // namespace ppc

View File

@@ -85,7 +85,7 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
PPCTranslator::~PPCTranslator() = default;
int PPCTranslator::Translate(FunctionInfo* symbol_info,
uint32_t debug_info_flags,
uint32_t debug_info_flags, uint32_t trace_flags,
Function** out_function) {
SCOPE_profile_cpu_f("alloy");
@@ -124,7 +124,16 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
}
// Emit function.
int result = builder_->Emit(symbol_info, debug_info != nullptr);
uint32_t emit_flags = 0;
if (debug_info) {
emit_flags |= PPCHIRBuilder::EMIT_DEBUG_COMMENTS;
}
if (trace_flags & TRACE_SOURCE_VALUES) {
emit_flags |= PPCHIRBuilder::EMIT_TRACE_SOURCE_VALUES;
} else if (trace_flags & TRACE_SOURCE) {
emit_flags |= PPCHIRBuilder::EMIT_TRACE_SOURCE;
}
int result = builder_->Emit(symbol_info, emit_flags);
if (result) {
return result;
}
@@ -150,8 +159,9 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
}
// Assemble to backend machine code.
result = assembler_->Assemble(symbol_info, builder_.get(), debug_info_flags,
std::move(debug_info), out_function);
result =
assembler_->Assemble(symbol_info, builder_.get(), debug_info_flags,
std::move(debug_info), trace_flags, out_function);
if (result) {
return result;
}

View File

@@ -32,7 +32,7 @@ class PPCTranslator {
~PPCTranslator();
int Translate(runtime::FunctionInfo* symbol_info, uint32_t debug_info_flags,
runtime::Function** out_function);
uint32_t trace_flags, runtime::Function** out_function);
private:
void DumpSource(runtime::FunctionInfo* symbol_info,