arm_types: Add FPSCR to Arm::LocationDescriptor and make Arm::LocationDescriptor have a FauxO-like interface
This commit is contained in:
parent
be87038ffd
commit
93af160c97
10 changed files with 87 additions and 61 deletions
|
@ -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)));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue