arm_types: Add FPSCR to Arm::LocationDescriptor and make Arm::LocationDescriptor have a FauxO-like interface

This commit is contained in:
MerryMage 2016-08-01 20:03:13 +01:00
parent be87038ffd
commit 93af160c97
10 changed files with 87 additions and 61 deletions

View file

@ -1066,10 +1066,10 @@ void EmitX64::EmitTerminal(IR::Terminal terminal, Arm::LocationDescriptor initia
} }
void EmitX64::EmitTerminalInterpret(IR::Term::Interpret terminal, Arm::LocationDescriptor initial_location) { void EmitX64::EmitTerminalInterpret(IR::Term::Interpret terminal, Arm::LocationDescriptor initial_location) {
ASSERT_MSG(terminal.next.TFlag == initial_location.TFlag, "Unimplemented"); ASSERT_MSG(terminal.next.TFlag() == initial_location.TFlag(), "Unimplemented");
ASSERT_MSG(terminal.next.EFlag == initial_location.EFlag, "Unimplemented"); ASSERT_MSG(terminal.next.EFlag() == initial_location.EFlag(), "Unimplemented");
code->MOV(64, R(ABI_PARAM1), Imm64(terminal.next.arm_pc)); code->MOV(64, R(ABI_PARAM1), Imm64(terminal.next.PC()));
code->MOV(64, R(ABI_PARAM2), Imm64(reinterpret_cast<u64>(jit_interface))); code->MOV(64, R(ABI_PARAM2), Imm64(reinterpret_cast<u64>(jit_interface)));
code->MOV(32, MJitStateReg(Arm::Reg::PC), R(ABI_PARAM1)); code->MOV(32, MJitStateReg(Arm::Reg::PC), R(ABI_PARAM1));
code->MOV(64, R(RSP), MDisp(R15, offsetof(JitState, save_host_RSP))); code->MOV(64, R(RSP), MDisp(R15, offsetof(JitState, save_host_RSP)));
@ -1082,16 +1082,16 @@ void EmitX64::EmitTerminalReturnToDispatch(IR::Term::ReturnToDispatch, Arm::Loca
} }
void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationDescriptor initial_location) { void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationDescriptor initial_location) {
code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.arm_pc)); code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.PC()));
if (terminal.next.TFlag != initial_location.TFlag) { if (terminal.next.TFlag() != initial_location.TFlag()) {
if (terminal.next.TFlag) { if (terminal.next.TFlag()) {
code->OR(32, MJitStateCpsr(), Imm32(1 << 5)); code->OR(32, MJitStateCpsr(), Imm32(1 << 5));
} else { } else {
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 5))); code->AND(32, MJitStateCpsr(), Imm32(~(1 << 5)));
} }
} }
if (terminal.next.EFlag != initial_location.EFlag) { if (terminal.next.EFlag() != initial_location.EFlag()) {
if (terminal.next.EFlag) { if (terminal.next.EFlag()) {
code->OR(32, MJitStateCpsr(), Imm32(1 << 9)); code->OR(32, MJitStateCpsr(), Imm32(1 << 9));
} else { } else {
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 9))); code->AND(32, MJitStateCpsr(), Imm32(~(1 << 9)));

View file

@ -42,7 +42,7 @@ struct Jit::Impl {
bool TFlag = Common::Bit<5>(jit_state.Cpsr); bool TFlag = Common::Bit<5>(jit_state.Cpsr);
bool EFlag = Common::Bit<9>(jit_state.Cpsr); bool EFlag = Common::Bit<9>(jit_state.Cpsr);
Arm::LocationDescriptor descriptor{pc, TFlag, EFlag}; Arm::LocationDescriptor descriptor{pc, TFlag, EFlag, jit_state.Fpscr};
CodePtr code_ptr = GetBasicBlock(descriptor); CodePtr code_ptr = GetBasicBlock(descriptor);
return routines.RunCode(&jit_state, code_ptr, cycle_count); return routines.RunCode(&jit_state, code_ptr, cycle_count);

View file

@ -19,6 +19,8 @@ struct JitState {
std::array<u32, 16> Reg{}; // Current register file. std::array<u32, 16> Reg{}; // Current register file.
// TODO: Mode-specific register sets unimplemented. // TODO: Mode-specific register sets unimplemented.
u32 Fpscr = 0;
std::array<u32, SpillCount> Spill{}; // Spill. std::array<u32, SpillCount> Spill{}; // Spill.
// For internal use (See: Routines::RunCode) // For internal use (See: Routines::RunCode)

View file

@ -76,23 +76,53 @@ enum class SignExtendRotation {
}; };
struct LocationDescriptor { struct LocationDescriptor {
LocationDescriptor(u32 arm_pc, bool TFlag, bool EFlag) static constexpr u32 FPSCR_MASK = 0x3F79F9F;
: arm_pc(arm_pc), TFlag(TFlag), EFlag(EFlag) {}
u32 arm_pc; LocationDescriptor(u32 arm_pc, bool tflag, bool eflag, u32 fpscr)
bool TFlag; ///< Thumb / ARM : arm_pc(arm_pc), tflag(tflag), eflag(eflag), fpscr(fpscr & FPSCR_MASK) {}
bool EFlag; ///< Big / Little Endian
u32 PC() const { return arm_pc; }
bool TFlag() const { return tflag; }
bool EFlag() const { return eflag; }
u32 FPSCR() const { return fpscr; }
bool operator == (const LocationDescriptor& o) const { bool operator == (const LocationDescriptor& o) const {
return std::tie(arm_pc, TFlag, EFlag) == std::tie(o.arm_pc, o.TFlag, o.EFlag); return std::tie(arm_pc, tflag, eflag, fpscr) == std::tie(o.arm_pc, o.tflag, o.eflag, o.fpscr);
} }
LocationDescriptor SetPC(u32 new_arm_pc) const {
return LocationDescriptor(new_arm_pc, tflag, eflag, fpscr);
}
LocationDescriptor AdvancePC(s32 amount) const {
return LocationDescriptor(arm_pc + amount, tflag, eflag, fpscr);
}
LocationDescriptor SetTFlag(bool new_tflag) const {
return LocationDescriptor(arm_pc, new_tflag, eflag, fpscr);
}
LocationDescriptor SetEFlag(bool new_eflag) const {
return LocationDescriptor(arm_pc, tflag, new_eflag, fpscr);
}
LocationDescriptor SetFPSCR(u32 new_fpscr) const {
return LocationDescriptor(arm_pc, tflag, eflag, new_fpscr & FPSCR_MASK);
}
private:
u32 arm_pc;
bool tflag; ///< Thumb / ARM
bool eflag; ///< Big / Little Endian
u32 fpscr; ///< Floating point status control register
}; };
struct LocationDescriptorHash { struct LocationDescriptorHash {
size_t operator()(const LocationDescriptor& x) const { size_t operator()(const LocationDescriptor& x) const {
return std::hash<u64>()(static_cast<u64>(x.arm_pc) return std::hash<u64>()(static_cast<u64>(x.PC())
^ (static_cast<u64>(x.TFlag) << 32) ^ static_cast<u64>(x.TFlag())
^ (static_cast<u64>(x.EFlag) << 33)); ^ (static_cast<u64>(x.EFlag()) << 1)
^ (static_cast<u64>(x.FPSCR()) << 32));
} }
}; };

View file

@ -133,10 +133,11 @@ std::string DumpBlock(const IR::Block& block) {
std::string ret; std::string ret;
const auto loc_to_string = [](Arm::LocationDescriptor loc) -> std::string { const auto loc_to_string = [](Arm::LocationDescriptor loc) -> std::string {
return Common::StringFromFormat("{%u,%s,%s}", return Common::StringFromFormat("{%u,%s,%s,%u}",
loc.arm_pc, loc.PC(),
loc.TFlag ? "T" : "!T", loc.TFlag() ? "T" : "!T",
loc.EFlag ? "E" : "!E"); loc.EFlag() ? "E" : "!E",
loc.FPSCR());
}; };
ret += Common::StringFromFormat("Block: location=%s\n", loc_to_string(block.location).c_str()); ret += Common::StringFromFormat("Block: location=%s\n", loc_to_string(block.location).c_str());

View file

@ -15,8 +15,8 @@ void IREmitter::Unimplemented() {
} }
u32 IREmitter::PC() { u32 IREmitter::PC() {
u32 offset = current_location.TFlag ? 4 : 8; u32 offset = current_location.TFlag() ? 4 : 8;
return current_location.arm_pc + offset; return current_location.PC() + offset;
} }
u32 IREmitter::AlignPC(size_t alignment) { u32 IREmitter::AlignPC(size_t alignment) {
@ -55,7 +55,7 @@ void IREmitter::ALUWritePC(const IR::Value& value) {
} }
void IREmitter::BranchWritePC(const IR::Value& value) { void IREmitter::BranchWritePC(const IR::Value& value) {
if (!current_location.TFlag) { if (!current_location.TFlag()) {
auto new_pc = And(value, Imm32(0xFFFFFFFC)); auto new_pc = And(value, Imm32(0xFFFFFFFC));
Inst(IR::Opcode::SetRegister, { IR::Value(Reg::PC), new_pc }); Inst(IR::Opcode::SetRegister, { IR::Value(Reg::PC), new_pc });
} else { } else {
@ -211,17 +211,17 @@ IR::Value IREmitter::ReadMemory8(const IR::Value& vaddr) {
IR::Value IREmitter::ReadMemory16(const IR::Value& vaddr) { IR::Value IREmitter::ReadMemory16(const IR::Value& vaddr) {
auto value = Inst(IR::Opcode::ReadMemory16, {vaddr}); auto value = Inst(IR::Opcode::ReadMemory16, {vaddr});
return current_location.EFlag ? ByteReverseHalf(value) : value; return current_location.EFlag() ? ByteReverseHalf(value) : value;
} }
IR::Value IREmitter::ReadMemory32(const IR::Value& vaddr) { IR::Value IREmitter::ReadMemory32(const IR::Value& vaddr) {
auto value = Inst(IR::Opcode::ReadMemory32, {vaddr}); auto value = Inst(IR::Opcode::ReadMemory32, {vaddr});
return current_location.EFlag ? ByteReverseWord(value) : value; return current_location.EFlag() ? ByteReverseWord(value) : value;
} }
IR::Value IREmitter::ReadMemory64(const IR::Value& vaddr) { IR::Value IREmitter::ReadMemory64(const IR::Value& vaddr) {
auto value = Inst(IR::Opcode::ReadMemory64, {vaddr}); auto value = Inst(IR::Opcode::ReadMemory64, {vaddr});
return current_location.EFlag ? ByteReverseDual(value) : value; return current_location.EFlag() ? ByteReverseDual(value) : value;
} }
void IREmitter::WriteMemory8(const IR::Value& vaddr, const IR::Value& value) { void IREmitter::WriteMemory8(const IR::Value& vaddr, const IR::Value& value) {
@ -229,7 +229,7 @@ void IREmitter::WriteMemory8(const IR::Value& vaddr, const IR::Value& value) {
} }
void IREmitter::WriteMemory16(const IR::Value& vaddr, const IR::Value& value) { void IREmitter::WriteMemory16(const IR::Value& vaddr, const IR::Value& value) {
if (current_location.EFlag) { if (current_location.EFlag()) {
auto v = ByteReverseHalf(value); auto v = ByteReverseHalf(value);
Inst(IR::Opcode::WriteMemory16, {vaddr, v}); Inst(IR::Opcode::WriteMemory16, {vaddr, v});
} else { } else {
@ -238,7 +238,7 @@ void IREmitter::WriteMemory16(const IR::Value& vaddr, const IR::Value& value) {
} }
void IREmitter::WriteMemory32(const IR::Value& vaddr, const IR::Value& value) { void IREmitter::WriteMemory32(const IR::Value& vaddr, const IR::Value& value) {
if (current_location.EFlag) { if (current_location.EFlag()) {
auto v = ByteReverseWord(value); auto v = ByteReverseWord(value);
Inst(IR::Opcode::WriteMemory32, {vaddr, v}); Inst(IR::Opcode::WriteMemory32, {vaddr, v});
} else { } else {
@ -247,7 +247,7 @@ void IREmitter::WriteMemory32(const IR::Value& vaddr, const IR::Value& value) {
} }
void IREmitter::WriteMemory64(const IR::Value& vaddr, const IR::Value& value) { void IREmitter::WriteMemory64(const IR::Value& vaddr, const IR::Value& value) {
if (current_location.EFlag) { if (current_location.EFlag()) {
auto v = ByteReverseDual(value); auto v = ByteReverseDual(value);
Inst(IR::Opcode::WriteMemory64, {vaddr, v}); Inst(IR::Opcode::WriteMemory64, {vaddr, v});
} else { } else {

View file

@ -15,7 +15,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32); IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32);
IR::Block Translate(LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) { IR::Block Translate(LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) {
return (descriptor.TFlag ? TranslateThumb : TranslateArm)(descriptor, memory_read_32); return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_32);
} }
} // namespace Arm } // namespace Arm

View file

@ -27,7 +27,7 @@ enum class ConditionalState {
struct ArmTranslatorVisitor final { struct ArmTranslatorVisitor final {
explicit ArmTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) { explicit ArmTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) {
ASSERT_MSG(!descriptor.TFlag, "The processor must be in Arm mode"); ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode");
} }
IREmitter ir; IREmitter ir;
@ -44,8 +44,7 @@ struct ArmTranslatorVisitor final {
} }
bool LinkToNextInstruction() { bool LinkToNextInstruction() {
auto next_location = ir.current_location; auto next_location = ir.current_location.AdvancePC(4);
next_location.arm_pc += 4;
ir.SetTerm(IR::Term::LinkBlock{next_location}); ir.SetTerm(IR::Term::LinkBlock{next_location});
return false; return false;
} }
@ -315,7 +314,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
bool should_continue = true; bool should_continue = true;
while (should_continue && visitor.cond_state == ConditionalState::None) { while (should_continue && visitor.cond_state == ConditionalState::None) {
const u32 arm_pc = visitor.ir.current_location.arm_pc; const u32 arm_pc = visitor.ir.current_location.PC();
const u32 arm_instruction = (*memory_read_32)(arm_pc); const u32 arm_instruction = (*memory_read_32)(arm_pc);
const auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction); const auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction);
@ -329,7 +328,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
break; break;
} }
visitor.ir.current_location.arm_pc += 4; visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
visitor.ir.block.cycle_count++; visitor.ir.block.cycle_count++;
} }

View file

@ -21,7 +21,7 @@ namespace {
struct ThumbTranslatorVisitor final { struct ThumbTranslatorVisitor final {
explicit ThumbTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) { explicit ThumbTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) {
ASSERT_MSG(descriptor.TFlag, "The processor must be in Thumb mode"); ASSERT_MSG(descriptor.TFlag(), "The processor must be in Thumb mode");
} }
IREmitter ir; IREmitter ir;
@ -678,13 +678,10 @@ struct ThumbTranslatorVisitor final {
bool thumb16_SETEND(bool E) { bool thumb16_SETEND(bool E) {
// SETEND <endianness> // SETEND <endianness>
if (E == ir.current_location.EFlag) { if (E == ir.current_location.EFlag()) {
return true; return true;
} }
auto next_location = ir.current_location; ir.SetTerm(IR::Term::LinkBlock{ir.current_location.AdvancePC(2).SetEFlag(E)});
next_location.arm_pc += 2;
next_location.EFlag = E;
ir.SetTerm(IR::Term::LinkBlock{next_location});
return false; return false;
} }
@ -762,7 +759,7 @@ struct ThumbTranslatorVisitor final {
bool thumb16_BLX_reg(Reg m) { bool thumb16_BLX_reg(Reg m) {
// BLX <Rm> // BLX <Rm>
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.arm_pc + 2) | 1)); ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 2) | 1));
ir.BXWritePC(ir.GetRegister(m)); ir.BXWritePC(ir.GetRegister(m));
// TODO(optimization): Possible push RSB location // TODO(optimization): Possible push RSB location
ir.SetTerm(IR::Term::ReturnToDispatch{}); ir.SetTerm(IR::Term::ReturnToDispatch{});
@ -783,10 +780,8 @@ struct ThumbTranslatorVisitor final {
return thumb16_UDF(); return thumb16_UDF();
} }
// B<cond> <label> // B<cond> <label>
auto then_location = ir.current_location; auto then_location = ir.current_location.AdvancePC(imm32);
then_location.arm_pc += imm32; auto else_location = ir.current_location.AdvancePC(2);
auto else_location = ir.current_location;
else_location.arm_pc += 2;
ir.SetTerm(IR::Term::If{cond, IR::Term::LinkBlock{then_location}, IR::Term::LinkBlock{else_location}}); ir.SetTerm(IR::Term::If{cond, IR::Term::LinkBlock{then_location}, IR::Term::LinkBlock{else_location}});
return false; return false;
} }
@ -794,18 +789,16 @@ struct ThumbTranslatorVisitor final {
bool thumb16_B_t2(Imm11 imm11) { bool thumb16_B_t2(Imm11 imm11) {
s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4; s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4;
// B <label> // B <label>
auto next_location = ir.current_location; auto next_location = ir.current_location.AdvancePC(imm32);
next_location.arm_pc += imm32;
ir.SetTerm(IR::Term::LinkBlock{next_location}); ir.SetTerm(IR::Term::LinkBlock{next_location});
return false; return false;
} }
bool thumb32_BL_imm(Imm11 hi, Imm11 lo) { bool thumb32_BL_imm(Imm11 hi, Imm11 lo) {
s32 imm32 = Common::SignExtend<23, s32>((hi << 12) | (lo << 1)); s32 imm32 = Common::SignExtend<23, s32>((hi << 12) | (lo << 1)) + 4;
// BL <label> // BL <label>
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.arm_pc + 4) | 1)); ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
auto new_location = ir.current_location; auto new_location = ir.current_location.AdvancePC(imm32);
new_location.arm_pc = ir.PC() + imm32;
ir.SetTerm(IR::Term::LinkBlock{new_location}); ir.SetTerm(IR::Term::LinkBlock{new_location});
return false; return false;
} }
@ -816,10 +809,10 @@ struct ThumbTranslatorVisitor final {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
// BLX <label> // BLX <label>
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.arm_pc + 4) | 1)); ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
auto new_location = ir.current_location; auto new_location = ir.current_location
new_location.arm_pc = ir.AlignPC(4) + imm32; .SetPC(ir.AlignPC(4) + imm32)
new_location.TFlag = false; .SetTFlag(false);
ir.SetTerm(IR::Term::LinkBlock{new_location}); ir.SetTerm(IR::Term::LinkBlock{new_location});
return false; return false;
} }
@ -862,7 +855,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType mem
bool should_continue = true; bool should_continue = true;
while (should_continue) { while (should_continue) {
const u32 arm_pc = visitor.ir.current_location.arm_pc; const u32 arm_pc = visitor.ir.current_location.PC();
u32 thumb_instruction; u32 thumb_instruction;
ThumbInstSize inst_size; ThumbInstSize inst_size;
@ -884,7 +877,8 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType mem
} }
} }
visitor.ir.current_location.arm_pc += (inst_size == ThumbInstSize::Thumb16) ? 2 : 4; s32 advance_pc = (inst_size == ThumbInstSize::Thumb16) ? 2 : 4;
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(advance_pc);
visitor.ir.block.cycle_count++; visitor.ir.block.cycle_count++;
} }

View file

@ -239,7 +239,7 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e
printf("%zu [%x] = %llx\n", record.size, record.address, record.data); printf("%zu [%x] = %llx\n", record.size, record.address, record.data);
} }
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate({0, true, false}, MemoryRead32); Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate({0, true, false, 0}, MemoryRead32);
Dynarmic::Optimization::GetSetElimination(ir_block); Dynarmic::Optimization::GetSetElimination(ir_block);
Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block);
Dynarmic::Optimization::VerificationPass(ir_block); Dynarmic::Optimization::VerificationPass(ir_block);