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) {
ASSERT_MSG(terminal.next.TFlag == initial_location.TFlag, "Unimplemented");
ASSERT_MSG(terminal.next.EFlag == initial_location.EFlag, "Unimplemented");
ASSERT_MSG(terminal.next.TFlag() == initial_location.TFlag(), "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(32, MJitStateReg(Arm::Reg::PC), R(ABI_PARAM1));
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) {
code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.arm_pc));
if (terminal.next.TFlag != initial_location.TFlag) {
if (terminal.next.TFlag) {
code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.PC()));
if (terminal.next.TFlag() != initial_location.TFlag()) {
if (terminal.next.TFlag()) {
code->OR(32, MJitStateCpsr(), Imm32(1 << 5));
} else {
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 5)));
}
}
if (terminal.next.EFlag != initial_location.EFlag) {
if (terminal.next.EFlag) {
if (terminal.next.EFlag() != initial_location.EFlag()) {
if (terminal.next.EFlag()) {
code->OR(32, MJitStateCpsr(), Imm32(1 << 9));
} else {
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 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);
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.
// TODO: Mode-specific register sets unimplemented.
u32 Fpscr = 0;
std::array<u32, SpillCount> Spill{}; // Spill.
// For internal use (See: Routines::RunCode)

View file

@ -76,23 +76,53 @@ enum class SignExtendRotation {
};
struct LocationDescriptor {
LocationDescriptor(u32 arm_pc, bool TFlag, bool EFlag)
: arm_pc(arm_pc), TFlag(TFlag), EFlag(EFlag) {}
static constexpr u32 FPSCR_MASK = 0x3F79F9F;
u32 arm_pc;
bool TFlag; ///< Thumb / ARM
bool EFlag; ///< Big / Little Endian
LocationDescriptor(u32 arm_pc, bool tflag, bool eflag, u32 fpscr)
: arm_pc(arm_pc), tflag(tflag), eflag(eflag), fpscr(fpscr & FPSCR_MASK) {}
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 {
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 {
size_t operator()(const LocationDescriptor& x) const {
return std::hash<u64>()(static_cast<u64>(x.arm_pc)
^ (static_cast<u64>(x.TFlag) << 32)
^ (static_cast<u64>(x.EFlag) << 33));
return std::hash<u64>()(static_cast<u64>(x.PC())
^ static_cast<u64>(x.TFlag())
^ (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;
const auto loc_to_string = [](Arm::LocationDescriptor loc) -> std::string {
return Common::StringFromFormat("{%u,%s,%s}",
loc.arm_pc,
loc.TFlag ? "T" : "!T",
loc.EFlag ? "E" : "!E");
return Common::StringFromFormat("{%u,%s,%s,%u}",
loc.PC(),
loc.TFlag() ? "T" : "!T",
loc.EFlag() ? "E" : "!E",
loc.FPSCR());
};
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 offset = current_location.TFlag ? 4 : 8;
return current_location.arm_pc + offset;
u32 offset = current_location.TFlag() ? 4 : 8;
return current_location.PC() + offset;
}
u32 IREmitter::AlignPC(size_t alignment) {
@ -55,7 +55,7 @@ void IREmitter::ALUWritePC(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));
Inst(IR::Opcode::SetRegister, { IR::Value(Reg::PC), new_pc });
} else {
@ -211,17 +211,17 @@ IR::Value IREmitter::ReadMemory8(const IR::Value& vaddr) {
IR::Value IREmitter::ReadMemory16(const IR::Value& 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) {
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) {
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) {
@ -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) {
if (current_location.EFlag) {
if (current_location.EFlag()) {
auto v = ByteReverseHalf(value);
Inst(IR::Opcode::WriteMemory16, {vaddr, v});
} 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) {
if (current_location.EFlag) {
if (current_location.EFlag()) {
auto v = ByteReverseWord(value);
Inst(IR::Opcode::WriteMemory32, {vaddr, v});
} 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) {
if (current_location.EFlag) {
if (current_location.EFlag()) {
auto v = ByteReverseDual(value);
Inst(IR::Opcode::WriteMemory64, {vaddr, v});
} 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 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

View file

@ -27,7 +27,7 @@ enum class ConditionalState {
struct ArmTranslatorVisitor final {
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;
@ -44,8 +44,7 @@ struct ArmTranslatorVisitor final {
}
bool LinkToNextInstruction() {
auto next_location = ir.current_location;
next_location.arm_pc += 4;
auto next_location = ir.current_location.AdvancePC(4);
ir.SetTerm(IR::Term::LinkBlock{next_location});
return false;
}
@ -315,7 +314,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
bool should_continue = true;
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 auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction);
@ -329,7 +328,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
break;
}
visitor.ir.current_location.arm_pc += 4;
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
visitor.ir.block.cycle_count++;
}

View file

@ -21,7 +21,7 @@ namespace {
struct ThumbTranslatorVisitor final {
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;
@ -678,13 +678,10 @@ struct ThumbTranslatorVisitor final {
bool thumb16_SETEND(bool E) {
// SETEND <endianness>
if (E == ir.current_location.EFlag) {
if (E == ir.current_location.EFlag()) {
return true;
}
auto next_location = ir.current_location;
next_location.arm_pc += 2;
next_location.EFlag = E;
ir.SetTerm(IR::Term::LinkBlock{next_location});
ir.SetTerm(IR::Term::LinkBlock{ir.current_location.AdvancePC(2).SetEFlag(E)});
return false;
}
@ -762,7 +759,7 @@ struct ThumbTranslatorVisitor final {
bool thumb16_BLX_reg(Reg m) {
// 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));
// TODO(optimization): Possible push RSB location
ir.SetTerm(IR::Term::ReturnToDispatch{});
@ -783,10 +780,8 @@ struct ThumbTranslatorVisitor final {
return thumb16_UDF();
}
// B<cond> <label>
auto then_location = ir.current_location;
then_location.arm_pc += imm32;
auto else_location = ir.current_location;
else_location.arm_pc += 2;
auto then_location = ir.current_location.AdvancePC(imm32);
auto else_location = ir.current_location.AdvancePC(2);
ir.SetTerm(IR::Term::If{cond, IR::Term::LinkBlock{then_location}, IR::Term::LinkBlock{else_location}});
return false;
}
@ -794,18 +789,16 @@ struct ThumbTranslatorVisitor final {
bool thumb16_B_t2(Imm11 imm11) {
s32 imm32 = Common::SignExtend<12, s32>(imm11 << 1) + 4;
// B <label>
auto next_location = ir.current_location;
next_location.arm_pc += imm32;
auto next_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{next_location});
return false;
}
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>
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.arm_pc + 4) | 1));
auto new_location = ir.current_location;
new_location.arm_pc = ir.PC() + imm32;
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
auto new_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{new_location});
return false;
}
@ -816,10 +809,10 @@ struct ThumbTranslatorVisitor final {
return UnpredictableInstruction();
}
// BLX <label>
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.arm_pc + 4) | 1));
auto new_location = ir.current_location;
new_location.arm_pc = ir.AlignPC(4) + imm32;
new_location.TFlag = false;
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
auto new_location = ir.current_location
.SetPC(ir.AlignPC(4) + imm32)
.SetTFlag(false);
ir.SetTerm(IR::Term::LinkBlock{new_location});
return false;
}
@ -862,7 +855,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType mem
bool should_continue = true;
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;
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++;
}

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);
}
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::DeadCodeElimination(ir_block);
Dynarmic::Optimization::VerificationPass(ir_block);