Label A32 specific code appropriately

This commit is contained in:
MerryMage
2018-01-01 15:23:56 +00:00
parent 89e9ce8aff
commit b3c73e2622
58 changed files with 938 additions and 831 deletions

View File

@@ -13,6 +13,7 @@
#include <fmt/ostream.h>
#include "common/assert.h"
#include "frontend/A32/types.h"
#include "frontend/ir/basic_block.h"
#include "frontend/ir/opcodes.h"
@@ -43,11 +44,11 @@ void Block::SetEndLocation(const LocationDescriptor& descriptor) {
end_location = descriptor;
}
Arm::Cond Block::GetCondition() const {
Cond Block::GetCondition() const {
return cond;
}
void Block::SetCondition(Arm::Cond condition) {
void Block::SetCondition(Cond condition) {
cond = condition;
}
@@ -122,7 +123,7 @@ static std::string TerminalToString(const Terminal& terminal_variant) {
}
case 6: {
auto terminal = boost::get<IR::Term::If>(terminal_variant);
return fmt::format("If{{{}, {}, {}}}", CondToString(terminal.if_), TerminalToString(terminal.then_), TerminalToString(terminal.else_));
return fmt::format("If{{{}, {}, {}}}", A32::CondToString(terminal.if_), TerminalToString(terminal.then_), TerminalToString(terminal.else_));
}
case 7: {
auto terminal = boost::get<IR::Term::CheckHalt>(terminal_variant);
@@ -138,8 +139,8 @@ std::string DumpBlock(const IR::Block& block) {
ret += fmt::format("Block: location={}\n", block.Location());
ret += fmt::format("cycles={}", block.CycleCount());
ret += fmt::format(", entry_cond={}", Arm::CondToString(block.GetCondition(), true));
if (block.GetCondition() != Arm::Cond::AL) {
ret += fmt::format(", entry_cond={}", A32::CondToString(block.GetCondition(), true));
if (block.GetCondition() != Cond::AL) {
ret += fmt::format(", cond_fail={}", block.ConditionFailedLocation());
}
ret += '\n';
@@ -161,9 +162,9 @@ std::string DumpBlock(const IR::Block& block) {
case Type::U32:
return fmt::format("#{:#x}", arg.GetU32());
case Type::RegRef:
return Arm::RegToString(arg.GetRegRef());
return A32::RegToString(arg.GetA32RegRef());
case Type::ExtRegRef:
return Arm::ExtRegToString(arg.GetExtRegRef());
return A32::ExtRegToString(arg.GetA32ExtRegRef());
default:
return "<unknown immediate type>";
}

View File

@@ -15,6 +15,7 @@
#include "common/common_types.h"
#include "common/intrusive_list.h"
#include "common/memory_pool.h"
#include "frontend/ir/cond.h"
#include "frontend/ir/location_descriptor.h"
#include "frontend/ir/microinstruction.h"
#include "frontend/ir/terminal.h"
@@ -85,9 +86,9 @@ public:
void SetEndLocation(const LocationDescriptor& descriptor);
/// Gets the condition required to pass in order to execute this block.
Arm::Cond GetCondition() const;
Cond GetCondition() const;
/// Sets the condition required to pass in order to execute this block.
void SetCondition(Arm::Cond condition);
void SetCondition(Cond condition);
/// Gets the location of the block to execute if the predicated condition fails.
LocationDescriptor ConditionFailedLocation() const;
@@ -124,7 +125,7 @@ private:
/// Description of the end location of this block
LocationDescriptor end_location;
/// Conditional to pass in order to execute this block
Arm::Cond cond = Arm::Cond::AL;
Cond cond = Cond::AL;
/// Block to execute next if `cond` did not pass.
boost::optional<LocationDescriptor> cond_failed = {};
/// Number of cycles this block takes to execute if the conditional fails.

24
src/frontend/ir/cond.h Normal file
View File

@@ -0,0 +1,24 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include "common/common_types.h"
namespace Dynarmic {
namespace IR {
enum class Cond {
EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
HS = CS, LO = CC,
};
inline Cond invert(Cond c) {
return static_cast<Cond>(static_cast<size_t>(c) ^ 1);
}
} // namespace IR
} // namespace Dynarmic

View File

@@ -11,256 +11,256 @@
namespace Dynarmic {
namespace IR {
void IREmitter::Unimplemented() {
void A32IREmitter::Unimplemented() {
}
u32 IREmitter::PC() {
u32 A32IREmitter::PC() {
u32 offset = current_location.TFlag() ? 4 : 8;
return current_location.PC() + offset;
}
u32 IREmitter::AlignPC(size_t alignment) {
u32 A32IREmitter::AlignPC(size_t alignment) {
u32 pc = PC();
return static_cast<u32>(pc - pc % alignment);
}
Value IREmitter::Imm1(bool imm1) {
Value A32IREmitter::Imm1(bool imm1) {
return Value(imm1);
}
Value IREmitter::Imm8(u8 imm8) {
Value A32IREmitter::Imm8(u8 imm8) {
return Value(imm8);
}
Value IREmitter::Imm32(u32 imm32) {
Value A32IREmitter::Imm32(u32 imm32) {
return Value(imm32);
}
Value IREmitter::Imm64(u64 imm64) {
Value A32IREmitter::Imm64(u64 imm64) {
return Value(imm64);
}
Value IREmitter::GetRegister(Arm::Reg reg) {
if (reg == Arm::Reg::PC) {
Value A32IREmitter::GetRegister(A32::Reg reg) {
if (reg == A32::Reg::PC) {
return Imm32(PC());
}
return Inst(Opcode::GetRegister, { Value(reg) });
}
Value IREmitter::GetExtendedRegister(Arm::ExtReg reg) {
if (Arm::IsSingleExtReg(reg)) {
Value A32IREmitter::GetExtendedRegister(A32::ExtReg reg) {
if (A32::IsSingleExtReg(reg)) {
return Inst(Opcode::GetExtendedRegister32, {Value(reg)});
}
if (Arm::IsDoubleExtReg(reg)) {
if (A32::IsDoubleExtReg(reg)) {
return Inst(Opcode::GetExtendedRegister64, {Value(reg)});
}
ASSERT_MSG(false, "Invalid reg.");
}
void IREmitter::SetRegister(const Arm::Reg reg, const Value& value) {
ASSERT(reg != Arm::Reg::PC);
void A32IREmitter::SetRegister(const A32::Reg reg, const Value& value) {
ASSERT(reg != A32::Reg::PC);
Inst(Opcode::SetRegister, { Value(reg), value });
}
void IREmitter::SetExtendedRegister(const Arm::ExtReg reg, const Value& value) {
if (Arm::IsSingleExtReg(reg)) {
void A32IREmitter::SetExtendedRegister(const A32::ExtReg reg, const Value& value) {
if (A32::IsSingleExtReg(reg)) {
Inst(Opcode::SetExtendedRegister32, {Value(reg), value});
} else if (Arm::IsDoubleExtReg(reg)) {
} else if (A32::IsDoubleExtReg(reg)) {
Inst(Opcode::SetExtendedRegister64, {Value(reg), value});
} else {
ASSERT_MSG(false, "Invalid reg.");
}
}
void IREmitter::ALUWritePC(const Value& value) {
void A32IREmitter::ALUWritePC(const Value& value) {
// This behaviour is ARM version-dependent.
// The below implementation is for ARMv6k
BranchWritePC(value);
}
void IREmitter::BranchWritePC(const Value& value) {
void A32IREmitter::BranchWritePC(const Value& value) {
if (!current_location.TFlag()) {
auto new_pc = And(value, Imm32(0xFFFFFFFC));
Inst(Opcode::SetRegister, { Value(Arm::Reg::PC), new_pc });
Inst(Opcode::SetRegister, { Value(A32::Reg::PC), new_pc });
} else {
auto new_pc = And(value, Imm32(0xFFFFFFFE));
Inst(Opcode::SetRegister, { Value(Arm::Reg::PC), new_pc });
Inst(Opcode::SetRegister, { Value(A32::Reg::PC), new_pc });
}
}
void IREmitter::BXWritePC(const Value& value) {
void A32IREmitter::BXWritePC(const Value& value) {
Inst(Opcode::BXWritePC, {value});
}
void IREmitter::LoadWritePC(const Value& value) {
void A32IREmitter::LoadWritePC(const Value& value) {
// This behaviour is ARM version-dependent.
// The below implementation is for ARMv6k
BXWritePC(value);
}
void IREmitter::CallSupervisor(const Value& value) {
void A32IREmitter::CallSupervisor(const Value& value) {
Inst(Opcode::CallSupervisor, {value});
}
void IREmitter::PushRSB(const LocationDescriptor& return_location) {
void A32IREmitter::PushRSB(const A32::LocationDescriptor& return_location) {
Inst(Opcode::PushRSB, {Value(return_location.UniqueHash())});
}
Value IREmitter::GetCpsr() {
Value A32IREmitter::GetCpsr() {
return Inst(Opcode::GetCpsr, {});
}
void IREmitter::SetCpsr(const Value& value) {
void A32IREmitter::SetCpsr(const Value& value) {
Inst(Opcode::SetCpsr, {value});
}
void IREmitter::SetCpsrNZCV(const Value& value) {
void A32IREmitter::SetCpsrNZCV(const Value& value) {
Inst(Opcode::SetCpsrNZCV, {value});
}
void IREmitter::SetCpsrNZCVQ(const Value& value) {
void A32IREmitter::SetCpsrNZCVQ(const Value& value) {
Inst(Opcode::SetCpsrNZCVQ, {value});
}
Value IREmitter::GetCFlag() {
Value A32IREmitter::GetCFlag() {
return Inst(Opcode::GetCFlag, {});
}
void IREmitter::SetNFlag(const Value& value) {
void A32IREmitter::SetNFlag(const Value& value) {
Inst(Opcode::SetNFlag, {value});
}
void IREmitter::SetZFlag(const Value& value) {
void A32IREmitter::SetZFlag(const Value& value) {
Inst(Opcode::SetZFlag, {value});
}
void IREmitter::SetCFlag(const Value& value) {
void A32IREmitter::SetCFlag(const Value& value) {
Inst(Opcode::SetCFlag, {value});
}
void IREmitter::SetVFlag(const Value& value) {
void A32IREmitter::SetVFlag(const Value& value) {
Inst(Opcode::SetVFlag, {value});
}
void IREmitter::OrQFlag(const Value& value) {
void A32IREmitter::OrQFlag(const Value& value) {
Inst(Opcode::OrQFlag, {value});
}
Value IREmitter::GetGEFlags() {
Value A32IREmitter::GetGEFlags() {
return Inst(Opcode::GetGEFlags, {});
}
void IREmitter::SetGEFlags(const Value& value) {
void A32IREmitter::SetGEFlags(const Value& value) {
Inst(Opcode::SetGEFlags, {value});
}
void IREmitter::SetGEFlagsCompressed(const Value& value) {
void A32IREmitter::SetGEFlagsCompressed(const Value& value) {
Inst(Opcode::SetGEFlagsCompressed, {value});
}
Value IREmitter::GetFpscr() {
Value A32IREmitter::GetFpscr() {
return Inst(Opcode::GetFpscr, {});
}
void IREmitter::SetFpscr(const Value& new_fpscr) {
void A32IREmitter::SetFpscr(const Value& new_fpscr) {
Inst(Opcode::SetFpscr, {new_fpscr});
}
Value IREmitter::GetFpscrNZCV() {
Value A32IREmitter::GetFpscrNZCV() {
return Inst(Opcode::GetFpscrNZCV, {});
}
void IREmitter::SetFpscrNZCV(const Value& new_fpscr_nzcv) {
void A32IREmitter::SetFpscrNZCV(const Value& new_fpscr_nzcv) {
Inst(Opcode::SetFpscrNZCV, {new_fpscr_nzcv});
}
Value IREmitter::Pack2x32To1x64(const Value& lo, const Value& hi) {
Value A32IREmitter::Pack2x32To1x64(const Value& lo, const Value& hi) {
return Inst(Opcode::Pack2x32To1x64, {lo, hi});
}
Value IREmitter::LeastSignificantWord(const Value& value) {
Value A32IREmitter::LeastSignificantWord(const Value& value) {
return Inst(Opcode::LeastSignificantWord, {value});
}
IREmitter::ResultAndCarry IREmitter::MostSignificantWord(const Value& value) {
A32IREmitter::ResultAndCarry A32IREmitter::MostSignificantWord(const Value& value) {
auto result = Inst(Opcode::MostSignificantWord, {value});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
return {result, carry_out};
}
Value IREmitter::LeastSignificantHalf(const Value& value) {
Value A32IREmitter::LeastSignificantHalf(const Value& value) {
return Inst(Opcode::LeastSignificantHalf, {value});
}
Value IREmitter::LeastSignificantByte(const Value& value) {
Value A32IREmitter::LeastSignificantByte(const Value& value) {
return Inst(Opcode::LeastSignificantByte, {value});
}
Value IREmitter::MostSignificantBit(const Value& value) {
Value A32IREmitter::MostSignificantBit(const Value& value) {
return Inst(Opcode::MostSignificantBit, {value});
}
Value IREmitter::IsZero(const Value& value) {
Value A32IREmitter::IsZero(const Value& value) {
return Inst(Opcode::IsZero, {value});
}
Value IREmitter::IsZero64(const Value& value) {
Value A32IREmitter::IsZero64(const Value& value) {
return Inst(Opcode::IsZero64, {value});
}
IREmitter::ResultAndCarry IREmitter::LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
A32IREmitter::ResultAndCarry A32IREmitter::LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
auto result = Inst(Opcode::LogicalShiftLeft, {value_in, shift_amount, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
return {result, carry_out};
}
IREmitter::ResultAndCarry IREmitter::LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
A32IREmitter::ResultAndCarry A32IREmitter::LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
auto result = Inst(Opcode::LogicalShiftRight, {value_in, shift_amount, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
return {result, carry_out};
}
Value IREmitter::LogicalShiftRight64(const Value& value_in, const Value& shift_amount) {
Value A32IREmitter::LogicalShiftRight64(const Value& value_in, const Value& shift_amount) {
return Inst(Opcode::LogicalShiftRight64, {value_in, shift_amount});
}
IREmitter::ResultAndCarry IREmitter::ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
A32IREmitter::ResultAndCarry A32IREmitter::ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
auto result = Inst(Opcode::ArithmeticShiftRight, {value_in, shift_amount, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
return {result, carry_out};
}
IREmitter::ResultAndCarry IREmitter::RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
A32IREmitter::ResultAndCarry A32IREmitter::RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) {
auto result = Inst(Opcode::RotateRight, {value_in, shift_amount, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
return {result, carry_out};
}
IREmitter::ResultAndCarry IREmitter::RotateRightExtended(const Value& value_in, const Value& carry_in) {
A32IREmitter::ResultAndCarry A32IREmitter::RotateRightExtended(const Value& value_in, const Value& carry_in) {
auto result = Inst(Opcode::RotateRightExtended, {value_in, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
return {result, carry_out};
}
IREmitter::ResultAndCarryAndOverflow IREmitter::AddWithCarry(const Value& a, const Value& b, const Value& carry_in) {
A32IREmitter::ResultAndCarryAndOverflow A32IREmitter::AddWithCarry(const Value& a, const Value& b, const Value& carry_in) {
auto result = Inst(Opcode::AddWithCarry, {a, b, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
auto overflow = Inst(Opcode::GetOverflowFromOp, {result});
return {result, carry_out, overflow};
}
Value IREmitter::Add(const Value& a, const Value& b) {
Value A32IREmitter::Add(const Value& a, const Value& b) {
return Inst(Opcode::AddWithCarry, {a, b, Imm1(0)});
}
Value IREmitter::Add64(const Value& a, const Value& b) {
Value A32IREmitter::Add64(const Value& a, const Value& b) {
return Inst(Opcode::Add64, {a, b});
}
IREmitter::ResultAndCarryAndOverflow IREmitter::SubWithCarry(const Value& a, const Value& b, const Value& carry_in) {
A32IREmitter::ResultAndCarryAndOverflow A32IREmitter::SubWithCarry(const Value& a, const Value& b, const Value& carry_in) {
// This is equivalent to AddWithCarry(a, Not(b), carry_in).
auto result = Inst(Opcode::SubWithCarry, {a, b, carry_in});
auto carry_out = Inst(Opcode::GetCarryFromOp, {result});
@@ -268,437 +268,437 @@ IREmitter::ResultAndCarryAndOverflow IREmitter::SubWithCarry(const Value& a, con
return {result, carry_out, overflow};
}
Value IREmitter::Sub(const Value& a, const Value& b) {
Value A32IREmitter::Sub(const Value& a, const Value& b) {
return Inst(Opcode::SubWithCarry, {a, b, Imm1(1)});
}
Value IREmitter::Sub64(const Value& a, const Value& b) {
Value A32IREmitter::Sub64(const Value& a, const Value& b) {
return Inst(Opcode::Sub64, {a, b});
}
Value IREmitter::Mul(const Value& a, const Value& b) {
Value A32IREmitter::Mul(const Value& a, const Value& b) {
return Inst(Opcode::Mul, {a, b});
}
Value IREmitter::Mul64(const Value& a, const Value& b) {
Value A32IREmitter::Mul64(const Value& a, const Value& b) {
return Inst(Opcode::Mul64, {a, b});
}
Value IREmitter::And(const Value& a, const Value& b) {
Value A32IREmitter::And(const Value& a, const Value& b) {
return Inst(Opcode::And, {a, b});
}
Value IREmitter::Eor(const Value& a, const Value& b) {
Value A32IREmitter::Eor(const Value& a, const Value& b) {
return Inst(Opcode::Eor, {a, b});
}
Value IREmitter::Or(const Value& a, const Value& b) {
Value A32IREmitter::Or(const Value& a, const Value& b) {
return Inst(Opcode::Or, {a, b});
}
Value IREmitter::Not(const Value& a) {
Value A32IREmitter::Not(const Value& a) {
return Inst(Opcode::Not, {a});
}
Value IREmitter::SignExtendWordToLong(const Value& a) {
Value A32IREmitter::SignExtendWordToLong(const Value& a) {
return Inst(Opcode::SignExtendWordToLong, {a});
}
Value IREmitter::SignExtendHalfToWord(const Value& a) {
Value A32IREmitter::SignExtendHalfToWord(const Value& a) {
return Inst(Opcode::SignExtendHalfToWord, {a});
}
Value IREmitter::SignExtendByteToWord(const Value& a) {
Value A32IREmitter::SignExtendByteToWord(const Value& a) {
return Inst(Opcode::SignExtendByteToWord, {a});
}
Value IREmitter::ZeroExtendWordToLong(const Value& a) {
Value A32IREmitter::ZeroExtendWordToLong(const Value& a) {
return Inst(Opcode::ZeroExtendWordToLong, {a});
}
Value IREmitter::ZeroExtendHalfToWord(const Value& a) {
Value A32IREmitter::ZeroExtendHalfToWord(const Value& a) {
return Inst(Opcode::ZeroExtendHalfToWord, {a});
}
Value IREmitter::ZeroExtendByteToWord(const Value& a) {
Value A32IREmitter::ZeroExtendByteToWord(const Value& a) {
return Inst(Opcode::ZeroExtendByteToWord, {a});
}
Value IREmitter::ByteReverseWord(const Value& a) {
Value A32IREmitter::ByteReverseWord(const Value& a) {
return Inst(Opcode::ByteReverseWord, {a});
}
Value IREmitter::ByteReverseHalf(const Value& a) {
Value A32IREmitter::ByteReverseHalf(const Value& a) {
return Inst(Opcode::ByteReverseHalf, {a});
}
Value IREmitter::ByteReverseDual(const Value& a) {
Value A32IREmitter::ByteReverseDual(const Value& a) {
return Inst(Opcode::ByteReverseDual, {a});
}
Value IREmitter::CountLeadingZeros(const Value& a) {
Value A32IREmitter::CountLeadingZeros(const Value& a) {
return Inst(Opcode::CountLeadingZeros, {a});
}
IREmitter::ResultAndOverflow IREmitter::SignedSaturatedAdd(const Value& a, const Value& b) {
A32IREmitter::ResultAndOverflow A32IREmitter::SignedSaturatedAdd(const Value& a, const Value& b) {
auto result = Inst(Opcode::SignedSaturatedAdd, {a, b});
auto overflow = Inst(Opcode::GetOverflowFromOp, {result});
return {result, overflow};
}
IREmitter::ResultAndOverflow IREmitter::SignedSaturatedSub(const Value& a, const Value& b) {
A32IREmitter::ResultAndOverflow A32IREmitter::SignedSaturatedSub(const Value& a, const Value& b) {
auto result = Inst(Opcode::SignedSaturatedSub, {a, b});
auto overflow = Inst(Opcode::GetOverflowFromOp, {result});
return {result, overflow};
}
IREmitter::ResultAndOverflow IREmitter::UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to) {
A32IREmitter::ResultAndOverflow A32IREmitter::UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to) {
ASSERT(bit_size_to_saturate_to <= 31);
auto result = Inst(Opcode::UnsignedSaturation, {a, Imm8(static_cast<u8>(bit_size_to_saturate_to))});
auto overflow = Inst(Opcode::GetOverflowFromOp, {result});
return {result, overflow};
}
IREmitter::ResultAndOverflow IREmitter::SignedSaturation(const Value& a, size_t bit_size_to_saturate_to) {
A32IREmitter::ResultAndOverflow A32IREmitter::SignedSaturation(const Value& a, size_t bit_size_to_saturate_to) {
ASSERT(bit_size_to_saturate_to >= 1 && bit_size_to_saturate_to <= 32);
auto result = Inst(Opcode::SignedSaturation, {a, Imm8(static_cast<u8>(bit_size_to_saturate_to))});
auto overflow = Inst(Opcode::GetOverflowFromOp, {result});
return {result, overflow};
}
IREmitter::ResultAndGE IREmitter::PackedAddU8(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedAddU8(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedAddU8, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedAddS8(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedAddS8(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedAddS8, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedAddU16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedAddU16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedAddU16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedAddS16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedAddS16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedAddS16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedSubU8(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedSubU8(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedSubU8, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedSubS8(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedSubS8(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedSubS8, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedSubU16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedSubU16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedSubU16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedSubS16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedSubS16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedSubS16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedAddSubU16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedAddSubU16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedAddSubU16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedAddSubS16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedAddSubS16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedAddSubS16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedSubAddU16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedSubAddU16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedSubAddU16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
IREmitter::ResultAndGE IREmitter::PackedSubAddS16(const Value& a, const Value& b) {
A32IREmitter::ResultAndGE A32IREmitter::PackedSubAddS16(const Value& a, const Value& b) {
auto result = Inst(Opcode::PackedSubAddS16, {a, b});
auto ge = Inst(Opcode::GetGEFromOp, {result});
return {result, ge};
}
Value IREmitter::PackedHalvingAddU8(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingAddU8(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingAddU8, {a, b});
}
Value IREmitter::PackedHalvingAddS8(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingAddS8(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingAddS8, {a, b});
}
Value IREmitter::PackedHalvingSubU8(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingSubU8(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingSubU8, {a, b});
}
Value IREmitter::PackedHalvingSubS8(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingSubS8(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingSubS8, {a, b});
}
Value IREmitter::PackedHalvingAddU16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingAddU16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingAddU16, {a, b});
}
Value IREmitter::PackedHalvingAddS16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingAddS16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingAddS16, {a, b});
}
Value IREmitter::PackedHalvingSubU16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingSubU16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingSubU16, {a, b});
}
Value IREmitter::PackedHalvingSubS16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingSubS16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingSubS16, {a, b});
}
Value IREmitter::PackedHalvingAddSubU16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingAddSubU16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingAddSubU16, {a, b});
}
Value IREmitter::PackedHalvingAddSubS16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingAddSubS16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingAddSubS16, {a, b});
}
Value IREmitter::PackedHalvingSubAddU16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingSubAddU16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingSubAddU16, {a, b});
}
Value IREmitter::PackedHalvingSubAddS16(const Value& a, const Value& b) {
Value A32IREmitter::PackedHalvingSubAddS16(const Value& a, const Value& b) {
return Inst(Opcode::PackedHalvingSubAddS16, {a, b});
}
Value IREmitter::PackedSaturatedAddU8(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedAddU8(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedAddU8, {a, b});
}
Value IREmitter::PackedSaturatedAddS8(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedAddS8(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedAddS8, {a, b});
}
Value IREmitter::PackedSaturatedSubU8(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedSubU8(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedSubU8, {a, b});
}
Value IREmitter::PackedSaturatedSubS8(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedSubS8(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedSubS8, {a, b});
}
Value IREmitter::PackedSaturatedAddU16(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedAddU16(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedAddU16, {a, b});
}
Value IREmitter::PackedSaturatedAddS16(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedAddS16(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedAddS16, {a, b});
}
Value IREmitter::PackedSaturatedSubU16(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedSubU16(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedSubU16, {a, b});
}
Value IREmitter::PackedSaturatedSubS16(const Value& a, const Value& b) {
Value A32IREmitter::PackedSaturatedSubS16(const Value& a, const Value& b) {
return Inst(Opcode::PackedSaturatedSubS16, {a, b});
}
Value IREmitter::PackedAbsDiffSumS8(const Value& a, const Value& b) {
Value A32IREmitter::PackedAbsDiffSumS8(const Value& a, const Value& b) {
return Inst(Opcode::PackedAbsDiffSumS8, {a, b});
}
Value IREmitter::PackedSelect(const Value& ge, const Value& a, const Value& b) {
Value A32IREmitter::PackedSelect(const Value& ge, const Value& a, const Value& b) {
return Inst(Opcode::PackedSelect, {ge, a, b});
}
Value IREmitter::TransferToFP32(const Value& a) {
Value A32IREmitter::TransferToFP32(const Value& a) {
return Inst(Opcode::TransferToFP32, {a});
}
Value IREmitter::TransferToFP64(const Value& a) {
Value A32IREmitter::TransferToFP64(const Value& a) {
return Inst(Opcode::TransferToFP64, {a});
}
Value IREmitter::TransferFromFP32(const Value& a) {
Value A32IREmitter::TransferFromFP32(const Value& a) {
return Inst(Opcode::TransferFromFP32, {a});
}
Value IREmitter::TransferFromFP64(const Value& a) {
Value A32IREmitter::TransferFromFP64(const Value& a) {
return Inst(Opcode::TransferFromFP64, {a});
}
Value IREmitter::FPAbs32(const Value& a) {
Value A32IREmitter::FPAbs32(const Value& a) {
return Inst(Opcode::FPAbs32, {a});
}
Value IREmitter::FPAbs64(const Value& a) {
Value A32IREmitter::FPAbs64(const Value& a) {
return Inst(Opcode::FPAbs64, {a});
}
Value IREmitter::FPAdd32(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPAdd32(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPAdd32, {a, b});
}
Value IREmitter::FPAdd64(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPAdd64(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPAdd64, {a, b});
}
void IREmitter::FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) {
void A32IREmitter::FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
Inst(Opcode::FPCompare32, {a, b, Imm1(exc_on_qnan)});
}
void IREmitter::FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) {
void A32IREmitter::FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
Inst(Opcode::FPCompare64, {a, b, Imm1(exc_on_qnan)});
}
Value IREmitter::FPDiv32(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPDiv32(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPDiv32, {a, b});
}
Value IREmitter::FPDiv64(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPDiv64(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPDiv64, {a, b});
}
Value IREmitter::FPMul32(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPMul32(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPMul32, {a, b});
}
Value IREmitter::FPMul64(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPMul64(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPMul64, {a, b});
}
Value IREmitter::FPNeg32(const Value& a) {
Value A32IREmitter::FPNeg32(const Value& a) {
return Inst(Opcode::FPNeg32, {a});
}
Value IREmitter::FPNeg64(const Value& a) {
Value A32IREmitter::FPNeg64(const Value& a) {
return Inst(Opcode::FPNeg64, {a});
}
Value IREmitter::FPSqrt32(const Value& a) {
Value A32IREmitter::FPSqrt32(const Value& a) {
return Inst(Opcode::FPSqrt32, {a});
}
Value IREmitter::FPSqrt64(const Value& a) {
Value A32IREmitter::FPSqrt64(const Value& a) {
return Inst(Opcode::FPSqrt64, {a});
}
Value IREmitter::FPSub32(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPSub32(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPSub32, {a, b});
}
Value IREmitter::FPSub64(const Value& a, const Value& b, bool fpscr_controlled) {
Value A32IREmitter::FPSub64(const Value& a, const Value& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPSub64, {a, b});
}
Value IREmitter::FPDoubleToSingle(const Value& a, bool fpscr_controlled) {
Value A32IREmitter::FPDoubleToSingle(const Value& a, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPDoubleToSingle, {a});
}
Value IREmitter::FPSingleToDouble(const Value& a, bool fpscr_controlled) {
Value A32IREmitter::FPSingleToDouble(const Value& a, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPSingleToDouble, {a});
}
Value IREmitter::FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
Value A32IREmitter::FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPSingleToS32, {a, Imm1(round_towards_zero)});
}
Value IREmitter::FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
Value A32IREmitter::FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPSingleToU32, {a, Imm1(round_towards_zero)});
}
Value IREmitter::FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
Value A32IREmitter::FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPDoubleToS32, {a, Imm1(round_towards_zero)});
}
Value IREmitter::FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
Value A32IREmitter::FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPDoubleToU32, {a, Imm1(round_towards_zero)});
}
Value IREmitter::FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
Value A32IREmitter::FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPS32ToSingle, {a, Imm1(round_to_nearest)});
}
Value IREmitter::FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
Value A32IREmitter::FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPU32ToSingle, {a, Imm1(round_to_nearest)});
}
Value IREmitter::FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
Value A32IREmitter::FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPS32ToDouble, {a, Imm1(round_to_nearest)});
}
Value IREmitter::FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
Value A32IREmitter::FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst(Opcode::FPU32ToDouble, {a, Imm1(round_to_nearest)});
}
void IREmitter::ClearExclusive() {
void A32IREmitter::ClearExclusive() {
Inst(Opcode::ClearExclusive, {});
}
void IREmitter::SetExclusive(const Value& vaddr, size_t byte_size) {
void A32IREmitter::SetExclusive(const Value& vaddr, size_t byte_size) {
ASSERT(byte_size == 1 || byte_size == 2 || byte_size == 4 || byte_size == 8 || byte_size == 16);
Inst(Opcode::SetExclusive, {vaddr, Imm8(u8(byte_size))});
}
Value IREmitter::ReadMemory8(const Value& vaddr) {
Value A32IREmitter::ReadMemory8(const Value& vaddr) {
return Inst(Opcode::ReadMemory8, {vaddr});
}
Value IREmitter::ReadMemory16(const Value& vaddr) {
Value A32IREmitter::ReadMemory16(const Value& vaddr) {
auto value = Inst(Opcode::ReadMemory16, {vaddr});
return current_location.EFlag() ? ByteReverseHalf(value) : value;
}
Value IREmitter::ReadMemory32(const Value& vaddr) {
Value A32IREmitter::ReadMemory32(const Value& vaddr) {
auto value = Inst(Opcode::ReadMemory32, {vaddr});
return current_location.EFlag() ? ByteReverseWord(value) : value;
}
Value IREmitter::ReadMemory64(const Value& vaddr) {
Value A32IREmitter::ReadMemory64(const Value& vaddr) {
auto value = Inst(Opcode::ReadMemory64, {vaddr});
return current_location.EFlag() ? ByteReverseDual(value) : value;
}
void IREmitter::WriteMemory8(const Value& vaddr, const Value& value) {
void A32IREmitter::WriteMemory8(const Value& vaddr, const Value& value) {
Inst(Opcode::WriteMemory8, {vaddr, value});
}
void IREmitter::WriteMemory16(const Value& vaddr, const Value& value) {
void A32IREmitter::WriteMemory16(const Value& vaddr, const Value& value) {
if (current_location.EFlag()) {
auto v = ByteReverseHalf(value);
Inst(Opcode::WriteMemory16, {vaddr, v});
@@ -707,7 +707,7 @@ void IREmitter::WriteMemory16(const Value& vaddr, const Value& value) {
}
}
void IREmitter::WriteMemory32(const Value& vaddr, const Value& value) {
void A32IREmitter::WriteMemory32(const Value& vaddr, const Value& value) {
if (current_location.EFlag()) {
auto v = ByteReverseWord(value);
Inst(Opcode::WriteMemory32, {vaddr, v});
@@ -716,7 +716,7 @@ void IREmitter::WriteMemory32(const Value& vaddr, const Value& value) {
}
}
void IREmitter::WriteMemory64(const Value& vaddr, const Value& value) {
void A32IREmitter::WriteMemory64(const Value& vaddr, const Value& value) {
if (current_location.EFlag()) {
auto v = ByteReverseDual(value);
Inst(Opcode::WriteMemory64, {vaddr, v});
@@ -725,11 +725,11 @@ void IREmitter::WriteMemory64(const Value& vaddr, const Value& value) {
}
}
Value IREmitter::ExclusiveWriteMemory8(const Value& vaddr, const Value& value) {
Value A32IREmitter::ExclusiveWriteMemory8(const Value& vaddr, const Value& value) {
return Inst(Opcode::ExclusiveWriteMemory8, {vaddr, value});
}
Value IREmitter::ExclusiveWriteMemory16(const Value& vaddr, const Value& value) {
Value A32IREmitter::ExclusiveWriteMemory16(const Value& vaddr, const Value& value) {
if (current_location.EFlag()) {
auto v = ByteReverseHalf(value);
return Inst(Opcode::ExclusiveWriteMemory16, {vaddr, v});
@@ -738,7 +738,7 @@ Value IREmitter::ExclusiveWriteMemory16(const Value& vaddr, const Value& value)
}
}
Value IREmitter::ExclusiveWriteMemory32(const Value& vaddr, const Value& value) {
Value A32IREmitter::ExclusiveWriteMemory32(const Value& vaddr, const Value& value) {
if (current_location.EFlag()) {
auto v = ByteReverseWord(value);
return Inst(Opcode::ExclusiveWriteMemory32, {vaddr, v});
@@ -747,7 +747,7 @@ Value IREmitter::ExclusiveWriteMemory32(const Value& vaddr, const Value& value)
}
}
Value IREmitter::ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi) {
Value A32IREmitter::ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi) {
if (current_location.EFlag()) {
auto vlo = ByteReverseWord(value_lo);
auto vhi = ByteReverseWord(value_hi);
@@ -757,7 +757,7 @@ Value IREmitter::ExclusiveWriteMemory64(const Value& vaddr, const Value& value_l
}
}
void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRd, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2) {
void A32IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRd, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -769,7 +769,7 @@ void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1,
Inst(Opcode::CoprocInternalOperation, {Value(coproc_info)});
}
void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2, const Value& word) {
void A32IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2, const Value& word) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -780,7 +780,7 @@ void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, Arm::
Inst(Opcode::CoprocSendOneWord, {Value(coproc_info), word});
}
void IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm, const Value& word1, const Value& word2) {
void A32IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm, const Value& word1, const Value& word2) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -789,7 +789,7 @@ void IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, Arm::
Inst(Opcode::CoprocSendTwoWords, {Value(coproc_info), word1, word2});
}
Value IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2) {
Value A32IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -800,7 +800,7 @@ Value IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, Arm::
return Inst(Opcode::CoprocGetOneWord, {Value(coproc_info)});
}
Value IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm) {
Value A32IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -809,7 +809,7 @@ Value IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, Arm::
return Inst(Opcode::CoprocGetTwoWords, {Value(coproc_info)});
}
void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option) {
void A32IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -820,7 +820,7 @@ void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer,
Inst(Opcode::CoprocLoadWords, {Value(coproc_info), address});
}
void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option) {
void A32IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
@@ -831,15 +831,15 @@ void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer,
Inst(Opcode::CoprocStoreWords, {Value(coproc_info), address});
}
void IREmitter::Breakpoint() {
void A32IREmitter::Breakpoint() {
Inst(Opcode::Breakpoint, {});
}
void IREmitter::SetTerm(const Terminal& terminal) {
void A32IREmitter::SetTerm(const Terminal& terminal) {
block.SetTerminal(terminal);
}
Value IREmitter::Inst(Opcode op, std::initializer_list<Value> args) {
Value A32IREmitter::Inst(Opcode op, std::initializer_list<Value> args) {
block.AppendNewInst(op, args);
return Value(&block.back());
}

View File

@@ -11,6 +11,8 @@
#include <dynarmic/coprocessor_util.h>
#include "common/common_types.h"
#include "frontend/A32/location_descriptor.h"
#include "frontend/A32/types.h"
#include "frontend/ir/basic_block.h"
#include "frontend/ir/location_descriptor.h"
#include "frontend/ir/terminal.h"
@@ -33,12 +35,12 @@ enum class Opcode;
* `block` is the resulting block.
* The user of this class updates `current_location` as appropriate.
*/
class IREmitter {
class A32IREmitter {
public:
explicit IREmitter(LocationDescriptor descriptor) : block(descriptor), current_location(descriptor) {}
explicit A32IREmitter(A32::LocationDescriptor descriptor) : block(descriptor), current_location(descriptor) {}
Block block;
LocationDescriptor current_location;
A32::LocationDescriptor current_location;
struct ResultAndCarry {
Value result;
@@ -70,17 +72,17 @@ public:
Value Imm32(u32 value);
Value Imm64(u64 value);
Value GetRegister(Arm::Reg source_reg);
Value GetExtendedRegister(Arm::ExtReg source_reg);
void SetRegister(const Arm::Reg dest_reg, const Value& value);
void SetExtendedRegister(const Arm::ExtReg dest_reg, const Value& value);
Value GetRegister(A32::Reg source_reg);
Value GetExtendedRegister(A32::ExtReg source_reg);
void SetRegister(const A32::Reg dest_reg, const Value& value);
void SetExtendedRegister(const A32::ExtReg dest_reg, const Value& value);
void ALUWritePC(const Value& value);
void BranchWritePC(const Value& value);
void BXWritePC(const Value& value);
void LoadWritePC(const Value& value);
void CallSupervisor(const Value& value);
void PushRSB(const LocationDescriptor& return_location);
void PushRSB(const A32::LocationDescriptor& return_location);
Value GetCpsr();
void SetCpsr(const Value& value);
@@ -225,13 +227,13 @@ public:
Value ExclusiveWriteMemory32(const Value& vaddr, const Value& value);
Value ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi);
void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRd, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2);
void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2, const Value& word);
void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm, const Value& word1, const Value& word2);
Value CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2);
Value CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm);
void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option);
void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option);
void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRd, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2);
void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2, const Value& word);
void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm, const Value& word1, const Value& word2);
Value CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2);
Value CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm);
void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option);
void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option);
void Breakpoint();

View File

@@ -6,17 +6,14 @@
#include <ostream>
#include <fmt/format.h>
#include "frontend/ir/location_descriptor.h"
namespace Dynarmic {
namespace IR {
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& loc) {
o << fmt::format("{{{},{},{},{}}}",
loc.PC(),
loc.TFlag() ? "T" : "!T",
loc.EFlag() ? "E" : "!E",
loc.FPSCR().Value());
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) {
o << fmt::format("{{{{}}}}", descriptor.value);
return o;
}

View File

@@ -6,110 +6,42 @@
#pragma once
#include <functional>
#include <iosfwd>
#include <tuple>
#include "common/common_types.h"
#include "frontend/arm/FPSCR.h"
#include "frontend/arm/PSR.h"
namespace Dynarmic {
namespace IR {
/**
* LocationDescriptor describes the location of a basic block.
* The location is not solely based on the PC because other flags influence the way
* instructions should be translated. The CPSR.T flag is most notable since it
* tells us if the processor is in Thumb or Arm mode.
*/
class LocationDescriptor {
public:
// Indicates bits that should be preserved within descriptors.
static constexpr u32 CPSR_MODE_MASK = 0x00000220;
static constexpr u32 FPSCR_MODE_MASK = 0x03F79F00;
LocationDescriptor(u32 arm_pc, Arm::PSR cpsr, Arm::FPSCR fpscr)
: arm_pc(arm_pc), cpsr(cpsr.Value() & CPSR_MODE_MASK), fpscr(fpscr.Value() & FPSCR_MODE_MASK) {}
u32 PC() const { return arm_pc; }
bool TFlag() const { return cpsr.T(); }
bool EFlag() const { return cpsr.E(); }
Arm::PSR CPSR() const { return cpsr; }
Arm::FPSCR FPSCR() const { return fpscr; }
bool operator == (const LocationDescriptor& o) const {
return std::tie(arm_pc, cpsr, fpscr) == std::tie(o.arm_pc, o.cpsr, o.fpscr);
return value == o.value;
}
bool operator != (const LocationDescriptor& o) const {
return !operator==(o);
}
LocationDescriptor SetPC(u32 new_arm_pc) const {
return LocationDescriptor(new_arm_pc, cpsr, fpscr);
}
LocationDescriptor AdvancePC(int amount) const {
return LocationDescriptor(static_cast<u32>(arm_pc + amount), cpsr, fpscr);
}
LocationDescriptor SetTFlag(bool new_tflag) const {
Arm::PSR new_cpsr = cpsr;
new_cpsr.T(new_tflag);
return LocationDescriptor(arm_pc, new_cpsr, fpscr);
}
LocationDescriptor SetEFlag(bool new_eflag) const {
Arm::PSR new_cpsr = cpsr;
new_cpsr.E(new_eflag);
return LocationDescriptor(arm_pc, new_cpsr, fpscr);
}
LocationDescriptor SetFPSCR(u32 new_fpscr) const {
return LocationDescriptor(arm_pc, cpsr, Arm::FPSCR{new_fpscr & FPSCR_MODE_MASK});
}
u64 UniqueHash() const {
// This value MUST BE UNIQUE.
// This calculation has to match up with EmitX64::EmitTerminalPopRSBHint
u64 pc_u64 = u64(arm_pc) << 32;
u64 fpscr_u64 = u64(fpscr.Value());
u64 t_u64 = cpsr.T() ? 1 : 0;
u64 e_u64 = cpsr.E() ? 2 : 0;
return pc_u64 | fpscr_u64 | t_u64 | e_u64;
}
private:
u32 arm_pc; ///< Current program counter value.
Arm::PSR cpsr; ///< Current program status register.
Arm::FPSCR fpscr; ///< Floating point status control register.
u64 value;
};
/**
* Provides a string representation of a LocationDescriptor.
*
* @param o Output stream
* @param descriptor The descriptor to get a string representation of
*/
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor);
} // namespace IR
} // namespace A32
} // namespace Dynarmic
namespace std {
template <>
struct less<Dynarmic::IR::LocationDescriptor> {
bool operator()(const Dynarmic::IR::LocationDescriptor& x, const Dynarmic::IR::LocationDescriptor& y) const {
return x.UniqueHash() < y.UniqueHash();
return x.value < y.value;
}
};
template <>
struct hash<Dynarmic::IR::LocationDescriptor> {
size_t operator()(const Dynarmic::IR::LocationDescriptor& x) const {
return std::hash<u64>()(x.UniqueHash());
return std::hash<u64>()(x.value);
}
};
} // namespace std

View File

@@ -9,6 +9,7 @@
#include <boost/variant.hpp>
#include "common/common_types.h"
#include "frontend/ir/cond.h"
#include "frontend/ir/location_descriptor.h"
namespace Dynarmic {
@@ -83,8 +84,8 @@ using Terminal = boost::variant<
* on the run-time state of the ARM flags.
*/
struct If {
If(Arm::Cond if_, Terminal then_, Terminal else_) : if_(if_), then_(then_), else_(else_) {}
Arm::Cond if_;
If(Cond if_, Terminal then_, Terminal else_) : if_(if_), then_(then_), else_(else_) {}
Cond if_;
Terminal then_;
Terminal else_;
};

View File

@@ -15,12 +15,12 @@ Value::Value(Inst* value) : type(Type::Opaque) {
inner.inst = value;
}
Value::Value(Arm::Reg value) : type(Type::RegRef) {
inner.imm_regref = value;
Value::Value(A32::Reg value) : type(Type::RegRef) {
inner.imm_a32regref = value;
}
Value::Value(Arm::ExtReg value) : type(Type::ExtRegRef) {
inner.imm_extregref = value;
Value::Value(A32::ExtReg value) : type(Type::ExtRegRef) {
inner.imm_a32extregref = value;
}
Value::Value(bool value) : type(Type::U1) {
@@ -68,14 +68,14 @@ Type Value::GetType() const {
return type;
}
Arm::Reg Value::GetRegRef() const {
A32::Reg Value::GetA32RegRef() const {
ASSERT(type == Type::RegRef);
return inner.imm_regref;
return inner.imm_a32regref;
}
Arm::ExtReg Value::GetExtRegRef() const {
A32::ExtReg Value::GetA32ExtRegRef() const {
ASSERT(type == Type::ExtRegRef);
return inner.imm_extregref;
return inner.imm_a32extregref;
}
Inst* Value::GetInst() const {

View File

@@ -7,7 +7,7 @@
#pragma once
#include "common/common_types.h"
#include "frontend/arm/types.h"
#include "frontend/A32/types.h"
namespace Dynarmic {
namespace IR {
@@ -22,8 +22,8 @@ class Value final {
public:
Value() : type(Type::Void) {}
explicit Value(Inst* value);
explicit Value(Arm::Reg value);
explicit Value(Arm::ExtReg value);
explicit Value(A32::Reg value);
explicit Value(A32::ExtReg value);
explicit Value(bool value);
explicit Value(u8 value);
explicit Value(u16 value);
@@ -36,8 +36,8 @@ public:
Type GetType() const;
Inst* GetInst() const;
Arm::Reg GetRegRef() const;
Arm::ExtReg GetExtRegRef() const;
A32::Reg GetA32RegRef() const;
A32::ExtReg GetA32ExtRegRef() const;
bool GetU1() const;
u8 GetU8() const;
u16 GetU16() const;
@@ -50,8 +50,8 @@ private:
union {
Inst* inst; // type == Type::Opaque
Arm::Reg imm_regref;
Arm::ExtReg imm_extregref;
A32::Reg imm_a32regref;
A32::ExtReg imm_a32extregref;
bool imm_u1;
u8 imm_u8;
u16 imm_u16;