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>
|
|
|
|
|
2018-01-04 22:12:02 +01:00
|
|
|
#include <dynarmic/A32/coprocessor_util.h>
|
2016-12-31 12:17:47 +01:00
|
|
|
|
2016-08-17 16:53:36 +02:00
|
|
|
#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.
|
|
|
|
*/
|
2018-01-01 16:47:56 +01:00
|
|
|
class IREmitter {
|
2016-07-01 15:01:06 +02:00
|
|
|
public:
|
2018-01-01 16:47:56 +01:00
|
|
|
explicit IREmitter(IR::LocationDescriptor descriptor) : block(descriptor) {}
|
2016-07-04 15:37:50 +02:00
|
|
|
|
2016-08-25 18:36:42 +02:00
|
|
|
Block block;
|
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-12-15 23:33:20 +01:00
|
|
|
struct ResultAndOverflow {
|
|
|
|
Value result;
|
|
|
|
Value overflow;
|
|
|
|
};
|
|
|
|
|
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-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
|
|
|
|
2018-01-01 17:19:43 +01:00
|
|
|
void PushRSB(const LocationDescriptor& return_location);
|
|
|
|
|
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-15 23:33:20 +01:00
|
|
|
Value CountLeadingZeros(const Value& a);
|
|
|
|
|
|
|
|
ResultAndOverflow SignedSaturatedAdd(const Value& a, const Value& b);
|
|
|
|
ResultAndOverflow SignedSaturatedSub(const Value& a, const Value& b);
|
2016-12-21 15:16:48 +01:00
|
|
|
ResultAndOverflow UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to);
|
|
|
|
ResultAndOverflow SignedSaturation(const Value& a, size_t bit_size_to_saturate_to);
|
2016-12-15 23:33:20 +01:00
|
|
|
|
2016-12-04 21:52:33 +01:00
|
|
|
ResultAndGE PackedAddU8(const Value& a, const Value& b);
|
2016-12-18 17:25:41 +01:00
|
|
|
ResultAndGE PackedAddS8(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedAddU16(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedAddS16(const Value& a, const Value& b);
|
2016-12-05 01:27:59 +01:00
|
|
|
ResultAndGE PackedSubU8(const Value& a, const Value& b);
|
2016-12-18 17:25:41 +01:00
|
|
|
ResultAndGE PackedSubS8(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedSubU16(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedSubS16(const Value& a, const Value& b);
|
2017-03-24 16:56:24 +01:00
|
|
|
ResultAndGE PackedAddSubU16(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedAddSubS16(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedSubAddU16(const Value& a, const Value& b);
|
|
|
|
ResultAndGE PackedSubAddS16(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-12-22 13:02:24 +01:00
|
|
|
Value PackedHalvingSubS8(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-12-22 13:02:24 +01:00
|
|
|
Value PackedHalvingSubS16(const Value& a, const Value& b);
|
2017-03-24 16:56:24 +01:00
|
|
|
Value PackedHalvingAddSubU16(const Value& a, const Value& b);
|
|
|
|
Value PackedHalvingAddSubS16(const Value& a, const Value& b);
|
|
|
|
Value PackedHalvingSubAddU16(const Value& a, const Value& b);
|
|
|
|
Value PackedHalvingSubAddS16(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);
|
2016-12-17 20:52:22 +01:00
|
|
|
Value PackedAbsDiffSumS8(const Value& a, const Value& b);
|
2017-11-25 17:33:48 +01:00
|
|
|
Value PackedSelect(const Value& ge, const Value& a, const Value& b);
|
2016-08-25 18:36:42 +02:00
|
|
|
|
|
|
|
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);
|
2017-11-22 18:45:37 +01:00
|
|
|
void FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled);
|
|
|
|
void FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, 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-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
|
|
|
|
2018-01-01 16:47:56 +01:00
|
|
|
protected:
|
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
|