2016-07-01 15:01:06 +02:00
|
|
|
/* 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
|
|
|
|
|
2016-08-17 16:53:36 +02:00
|
|
|
#include <initializer_list>
|
|
|
|
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "frontend/ir/basic_block.h"
|
2016-09-05 12:54:09 +02:00
|
|
|
#include "frontend/ir/location_descriptor.h"
|
2016-08-17 16:53:36 +02:00
|
|
|
#include "frontend/ir/terminal.h"
|
|
|
|
#include "frontend/ir/value.h"
|
|
|
|
|
|
|
|
// ARM JIT Microinstruction Intermediate Representation
|
|
|
|
//
|
|
|
|
// This intermediate representation is an SSA IR. It is designed primarily for analysis,
|
|
|
|
// though it can be lowered into a reduced form for interpretation. Each IR node (Value)
|
|
|
|
// is a microinstruction of an idealised ARM CPU. The choice of microinstructions is made
|
|
|
|
// not based on any existing microarchitecture but on ease of implementation.
|
2016-07-01 15:01:06 +02:00
|
|
|
|
|
|
|
namespace Dynarmic {
|
2016-08-25 18:36:42 +02:00
|
|
|
namespace IR {
|
2016-07-01 15:01:06 +02:00
|
|
|
|
2016-09-03 22:48:03 +02:00
|
|
|
enum class Opcode;
|
|
|
|
|
2016-08-12 19:17:31 +02:00
|
|
|
/**
|
|
|
|
* Convenience class to construct a basic block of the intermediate representation.
|
|
|
|
* `block` is the resulting block.
|
|
|
|
* The user of this class updates `current_location` as appropriate.
|
|
|
|
*/
|
2016-07-01 15:01:06 +02:00
|
|
|
class IREmitter {
|
|
|
|
public:
|
2016-09-05 12:54:09 +02:00
|
|
|
explicit IREmitter(LocationDescriptor descriptor) : block(descriptor), current_location(descriptor) {}
|
2016-07-04 15:37:50 +02:00
|
|
|
|
2016-08-25 18:36:42 +02:00
|
|
|
Block block;
|
2016-09-05 12:54:09 +02:00
|
|
|
LocationDescriptor current_location;
|
2016-07-01 15:01:06 +02:00
|
|
|
|
|
|
|
struct ResultAndCarry {
|
2016-08-25 18:36:42 +02:00
|
|
|
Value result;
|
|
|
|
Value carry;
|
2016-07-01 15:01:06 +02:00
|
|
|
};
|
|
|
|
|
2016-07-08 11:09:18 +02:00
|
|
|
struct ResultAndCarryAndOverflow {
|
2016-08-25 18:36:42 +02:00
|
|
|
Value result;
|
|
|
|
Value carry;
|
|
|
|
Value overflow;
|
2016-07-08 11:09:18 +02:00
|
|
|
};
|
|
|
|
|
2016-12-04 21:52:33 +01:00
|
|
|
struct ResultAndGE {
|
|
|
|
Value result;
|
|
|
|
Value ge;
|
|
|
|
};
|
|
|
|
|
2016-07-01 15:01:06 +02:00
|
|
|
void Unimplemented();
|
2016-07-11 23:43:53 +02:00
|
|
|
u32 PC();
|
|
|
|
u32 AlignPC(size_t alignment);
|
2016-07-01 15:01:06 +02:00
|
|
|
|
2016-08-25 18:36:42 +02:00
|
|
|
Value Imm1(bool value);
|
|
|
|
Value Imm8(u8 value);
|
|
|
|
Value Imm32(u32 value);
|
2016-12-03 12:29:50 +01:00
|
|
|
Value Imm64(u64 value);
|
2016-08-25 18:36:42 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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);
|
2016-09-05 12:54:09 +02:00
|
|
|
void PushRSB(const LocationDescriptor& return_location);
|
2016-08-25 18:36:42 +02:00
|
|
|
|
|
|
|
Value GetCpsr();
|
|
|
|
void SetCpsr(const Value& value);
|
|
|
|
Value GetCFlag();
|
|
|
|
void SetNFlag(const Value& value);
|
|
|
|
void SetZFlag(const Value& value);
|
|
|
|
void SetCFlag(const Value& value);
|
|
|
|
void SetVFlag(const Value& value);
|
|
|
|
void OrQFlag(const Value& value);
|
2016-11-23 20:44:27 +01:00
|
|
|
Value GetGEFlags();
|
|
|
|
void SetGEFlags(const Value& value);
|
2016-08-25 18:36:42 +02:00
|
|
|
|
2016-08-26 23:47:54 +02:00
|
|
|
Value GetFpscr();
|
|
|
|
void SetFpscr(const Value& new_fpscr);
|
|
|
|
Value GetFpscrNZCV();
|
|
|
|
void SetFpscrNZCV(const Value& new_fpscr_nzcv);
|
|
|
|
|
2016-08-25 18:36:42 +02:00
|
|
|
Value Pack2x32To1x64(const Value& lo, const Value& hi);
|
|
|
|
Value LeastSignificantWord(const Value& value);
|
|
|
|
ResultAndCarry MostSignificantWord(const Value& value);
|
|
|
|
Value LeastSignificantHalf(const Value& value);
|
|
|
|
Value LeastSignificantByte(const Value& value);
|
|
|
|
Value MostSignificantBit(const Value& value);
|
|
|
|
Value IsZero(const Value& value);
|
|
|
|
Value IsZero64(const Value& value);
|
|
|
|
|
|
|
|
ResultAndCarry LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in);
|
|
|
|
ResultAndCarry LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in);
|
|
|
|
Value LogicalShiftRight64(const Value& value_in, const Value& shift_amount);
|
|
|
|
ResultAndCarry ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in);
|
|
|
|
ResultAndCarry RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in);
|
|
|
|
ResultAndCarry RotateRightExtended(const Value& value_in, const Value& carry_in);
|
|
|
|
ResultAndCarryAndOverflow AddWithCarry(const Value& a, const Value& b, const Value& carry_in);
|
|
|
|
Value Add(const Value& a, const Value& b);
|
|
|
|
Value Add64(const Value& a, const Value& b);
|
|
|
|
ResultAndCarryAndOverflow SubWithCarry(const Value& a, const Value& b, const Value& carry_in);
|
|
|
|
Value Sub(const Value& a, const Value& b);
|
|
|
|
Value Sub64(const Value& a, const Value& b);
|
|
|
|
Value Mul(const Value& a, const Value& b);
|
|
|
|
Value Mul64(const Value& a, const Value& b);
|
|
|
|
Value And(const Value& a, const Value& b);
|
|
|
|
Value Eor(const Value& a, const Value& b);
|
|
|
|
Value Or(const Value& a, const Value& b);
|
|
|
|
Value Not(const Value& a);
|
|
|
|
Value SignExtendWordToLong(const Value& a);
|
|
|
|
Value SignExtendHalfToWord(const Value& a);
|
|
|
|
Value SignExtendByteToWord(const Value& a);
|
|
|
|
Value ZeroExtendWordToLong(const Value& a);
|
|
|
|
Value ZeroExtendHalfToWord(const Value& a);
|
|
|
|
Value ZeroExtendByteToWord(const Value& a);
|
|
|
|
Value ByteReverseWord(const Value& a);
|
|
|
|
Value ByteReverseHalf(const Value& a);
|
|
|
|
Value ByteReverseDual(const Value& a);
|
2016-12-04 21:52:33 +01:00
|
|
|
ResultAndGE PackedAddU8(const Value& a, const Value& b);
|
2016-11-25 21:32:22 +01:00
|
|
|
Value PackedHalvingAddU8(const Value& a, const Value& b);
|
2016-11-26 19:12:29 +01:00
|
|
|
Value PackedHalvingAddS8(const Value& a, const Value& b);
|
2016-11-26 19:27:21 +01:00
|
|
|
Value PackedHalvingSubU8(const Value& a, const Value& b);
|
2016-11-26 12:28:20 +01:00
|
|
|
Value PackedHalvingAddU16(const Value& a, const Value& b);
|
2016-11-26 19:12:29 +01:00
|
|
|
Value PackedHalvingAddS16(const Value& a, const Value& b);
|
2016-11-26 19:27:21 +01:00
|
|
|
Value PackedHalvingSubU16(const Value& a, const Value& b);
|
2016-08-25 18:36:42 +02:00
|
|
|
Value PackedSaturatedAddU8(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedAddS8(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedSubU8(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedSubS8(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedAddU16(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedAddS16(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedSubU16(const Value& a, const Value& b);
|
|
|
|
Value PackedSaturatedSubS16(const Value& a, const Value& b);
|
|
|
|
|
|
|
|
Value TransferToFP32(const Value& a);
|
|
|
|
Value TransferToFP64(const Value& a);
|
|
|
|
Value TransferFromFP32(const Value& a);
|
|
|
|
Value TransferFromFP64(const Value& a);
|
|
|
|
Value FPAbs32(const Value& a);
|
|
|
|
Value FPAbs64(const Value& a);
|
|
|
|
Value FPAdd32(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPAdd64(const Value& a, const Value& b, bool fpscr_controlled);
|
2016-11-26 12:17:16 +01:00
|
|
|
void FPCompare32(const Value& a, const Value& b, bool quiet, bool fpscr_controlled);
|
|
|
|
void FPCompare64(const Value& a, const Value& b, bool quiet, bool fpscr_controlled);
|
2016-08-25 18:36:42 +02:00
|
|
|
Value FPDiv32(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPDiv64(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPMul32(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPMul64(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPNeg32(const Value& a);
|
|
|
|
Value FPNeg64(const Value& a);
|
|
|
|
Value FPSqrt32(const Value& a);
|
|
|
|
Value FPSqrt64(const Value& a);
|
|
|
|
Value FPSub32(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPSub64(const Value& a, const Value& b, bool fpscr_controlled);
|
|
|
|
Value FPDoubleToSingle(const Value& a, bool fpscr_controlled);
|
|
|
|
Value FPSingleToDouble(const Value& a, bool fpscr_controlled);
|
|
|
|
Value FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
|
|
|
|
Value FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
|
|
|
|
Value FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
|
|
|
|
Value FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
|
|
|
|
Value FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled);
|
|
|
|
Value FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled);
|
|
|
|
Value FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled);
|
|
|
|
Value FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled);
|
2016-08-06 18:21:29 +02:00
|
|
|
|
2016-09-02 13:17:22 +02:00
|
|
|
void ClearExclusive();
|
2016-08-25 18:36:42 +02:00
|
|
|
void SetExclusive(const Value& vaddr, size_t byte_size);
|
|
|
|
Value ReadMemory8(const Value& vaddr);
|
|
|
|
Value ReadMemory16(const Value& vaddr);
|
|
|
|
Value ReadMemory32(const Value& vaddr);
|
|
|
|
Value ReadMemory64(const Value& vaddr);
|
|
|
|
void WriteMemory8(const Value& vaddr, const Value& value);
|
|
|
|
void WriteMemory16(const Value& vaddr, const Value& value);
|
|
|
|
void WriteMemory32(const Value& vaddr, const Value& value);
|
|
|
|
void WriteMemory64(const Value& vaddr, const Value& value);
|
|
|
|
Value ExclusiveWriteMemory8(const Value& vaddr, const Value& value);
|
|
|
|
Value ExclusiveWriteMemory16(const Value& vaddr, const Value& value);
|
|
|
|
Value ExclusiveWriteMemory32(const Value& vaddr, const Value& value);
|
|
|
|
Value ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi);
|
2016-07-11 23:43:53 +02:00
|
|
|
|
2016-08-05 15:07:27 +02:00
|
|
|
void Breakpoint();
|
|
|
|
|
2016-08-25 18:36:42 +02:00
|
|
|
void SetTerm(const Terminal& terminal);
|
2016-07-07 11:53:09 +02:00
|
|
|
|
2016-07-01 15:01:06 +02:00
|
|
|
private:
|
2016-08-25 18:36:42 +02:00
|
|
|
Value Inst(Opcode op, std::initializer_list<Value> args);
|
2016-07-01 15:01:06 +02:00
|
|
|
};
|
|
|
|
|
2016-08-25 18:36:42 +02:00
|
|
|
} // namespace IR
|
2016-07-01 15:01:06 +02:00
|
|
|
} // namespace Dynarmic
|