2017-10-21 17:58:58 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
#include "dxbc_enums.h"
|
2017-10-29 02:35:16 +02:00
|
|
|
#include "dxbc_names.h"
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
class DxbcOperand;
|
2017-11-17 11:41:56 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/**
|
|
|
|
* \brief Component swizzle
|
|
|
|
*
|
|
|
|
* Maps vector components to
|
|
|
|
* other vector components.
|
|
|
|
*/
|
|
|
|
class DxbcRegSwizzle {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcRegSwizzle() { }
|
|
|
|
DxbcRegSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
|
|
|
|
: m_data((x << 0) | (y << 2) | (z << 4) | (w << 6)) { }
|
|
|
|
|
|
|
|
uint32_t operator [] (uint32_t id) const {
|
|
|
|
return (m_data >> (id + id)) & 0x3;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
uint8_t m_data = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Component mask
|
|
|
|
*
|
|
|
|
* Enables access to certain
|
|
|
|
* subset of vector components.
|
|
|
|
*/
|
|
|
|
class DxbcRegMask {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcRegMask() { }
|
|
|
|
DxbcRegMask(uint32_t mask) : m_data(mask) { }
|
|
|
|
DxbcRegMask(bool x, bool y, bool z, bool w)
|
|
|
|
: m_data((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
|
|
|
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
|
|
|
|
|
|
|
bool operator [] (uint32_t id) const {
|
|
|
|
return (m_data >> id) & 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t setCount() const {
|
|
|
|
const uint8_t n[16] = { 0, 1, 1, 2, 1, 2, 2, 3,
|
|
|
|
1, 2, 2, 3, 2, 3, 3, 4 };
|
|
|
|
return n[m_data & 0xF];
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t firstSet() const {
|
|
|
|
const uint8_t n[16] = { 4, 0, 1, 0, 2, 0, 1, 0,
|
|
|
|
3, 0, 1, 0, 2, 0, 1, 0 };
|
|
|
|
return n[m_data & 0xF];
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
uint8_t m_data = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-11-17 11:41:56 +01:00
|
|
|
/**
|
|
|
|
* \brief Basic control info
|
|
|
|
*
|
|
|
|
* Parses instruction-specific control bits. Whether
|
|
|
|
* these are well defined depends on the instruction.
|
|
|
|
*/
|
|
|
|
class DxbcOpcodeControl {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcOpcodeControl() { }
|
|
|
|
DxbcOpcodeControl(uint32_t control)
|
|
|
|
: m_control(control) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Saturation hint
|
|
|
|
*
|
|
|
|
* If set, the result of the given instruction
|
|
|
|
* is clamped to the [0..1] range.
|
|
|
|
*/
|
|
|
|
bool saturateBit() const {
|
|
|
|
return bit::extract(m_control, 2, 2) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Precision hint
|
|
|
|
*/
|
|
|
|
bool preciseBit() const {
|
|
|
|
return bit::extract(m_control, 8, 11) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Zero test
|
|
|
|
*
|
|
|
|
* For conditional instructions, this defines
|
|
|
|
* whether the test shall pass when the given
|
|
|
|
* operand is zero or non-zero.
|
|
|
|
*/
|
|
|
|
DxbcZeroTest zeroTest() const {
|
|
|
|
return static_cast<DxbcZeroTest>(
|
|
|
|
bit::extract(m_control, 7, 7));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Resinfo return type
|
|
|
|
*
|
|
|
|
* Control bits specifically for
|
|
|
|
* the \c resinfo instruction.
|
|
|
|
*/
|
|
|
|
DxbcResinfoType resinfoType() const {
|
|
|
|
return static_cast<DxbcResinfoType>(
|
|
|
|
bit::extract(m_control, 0, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Sync flags
|
|
|
|
*
|
|
|
|
* Defines the exact operation of sync
|
|
|
|
* instructions in compute shaders.
|
|
|
|
*/
|
|
|
|
DxbcSyncFlags syncFlags() const {
|
|
|
|
return bit::extract(m_control, 0, 3);
|
|
|
|
}
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/**
|
|
|
|
* \brief Resource dimension
|
|
|
|
*
|
|
|
|
* Defines the type of a resource.
|
|
|
|
* Only valid for dcl_resource etc.
|
|
|
|
*/
|
|
|
|
DxbcResourceDim resourceDim() const {
|
|
|
|
return static_cast<DxbcResourceDim>(
|
|
|
|
bit::extract(m_control, 0, 4));
|
|
|
|
}
|
|
|
|
|
2017-11-17 11:41:56 +01:00
|
|
|
private:
|
|
|
|
|
|
|
|
uint32_t m_control = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
/**
|
|
|
|
* \brief DXBC instruction token
|
|
|
|
*
|
|
|
|
* Initial token at the beginning of each instruction.
|
|
|
|
* This encodes the actual op code, the length of the
|
|
|
|
* entire instruction in DWORDs, as well as some flags
|
|
|
|
* controlling the specific instruction.
|
|
|
|
*/
|
|
|
|
class DxbcOpcodeToken {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcOpcodeToken() { }
|
|
|
|
DxbcOpcodeToken(uint32_t token)
|
|
|
|
: m_token(token) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Opcode
|
|
|
|
* \returns Opcode
|
|
|
|
*/
|
|
|
|
DxbcOpcode opcode() const {
|
|
|
|
return static_cast<DxbcOpcode>(
|
|
|
|
bit::extract(m_token, 0, 10));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Control info
|
|
|
|
*
|
|
|
|
* Instruction-specific control info. Undefined
|
|
|
|
* if the opcode is \c DxbcOpcode::CustomData.
|
|
|
|
* \returns Control info
|
|
|
|
*/
|
|
|
|
uint32_t control() const {
|
|
|
|
return bit::extract(m_token, 11, 23);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Instruction length
|
|
|
|
*
|
|
|
|
* Undefind if the opcode is \c DxbcOpcode::CustomData.
|
|
|
|
* In that case, the instruction length will be stored
|
|
|
|
* in the DWORD immediately following the opcode token.
|
|
|
|
* \returns Instruction length, in DWORDs
|
|
|
|
*/
|
|
|
|
uint32_t length() const {
|
|
|
|
return bit::extract(m_token, 24, 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Checks whether the opcode is extended
|
|
|
|
*
|
|
|
|
* Additional information is encoded in extended
|
|
|
|
* opcode tokens if this flag is set. Note that
|
|
|
|
* multiple extended opcode tokens may be chained.
|
|
|
|
* \returns \c true if the opcode is extended.
|
|
|
|
*/
|
|
|
|
bool isExtended() const {
|
|
|
|
return !!bit::extract(m_token, 31, 31);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
uint32_t m_token = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief DXBC extended instruction token
|
|
|
|
*
|
|
|
|
* Some instruction may encode additional control
|
|
|
|
* modifiers in extended opcode tokens. The format
|
|
|
|
* of these tokens differs from that of the the
|
|
|
|
* initial opcode tokens.
|
|
|
|
*/
|
|
|
|
class DxbcOpcodeTokenExt {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcOpcodeTokenExt() { }
|
|
|
|
DxbcOpcodeTokenExt(uint32_t token)
|
|
|
|
: m_token(token) { }
|
|
|
|
|
2017-10-22 23:13:29 +02:00
|
|
|
/**
|
|
|
|
* \brief Extended opcode
|
|
|
|
* \returns Extended opcode
|
|
|
|
*/
|
|
|
|
DxbcExtOpcode opcode() const {
|
|
|
|
return static_cast<DxbcExtOpcode>(
|
|
|
|
bit::extract(m_token, 0, 5));
|
|
|
|
}
|
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
/**
|
|
|
|
* \brief Control info
|
|
|
|
*
|
|
|
|
* Instruction-specific control info. Undefined
|
|
|
|
* if the opcode is \c DxbcOpcode::CustomData.
|
|
|
|
* \returns Control info
|
|
|
|
*/
|
|
|
|
uint32_t control() const {
|
|
|
|
return bit::extract(m_token, 6, 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Extended opcode length
|
|
|
|
*
|
|
|
|
* Number of DWORDs that belong to this extended
|
|
|
|
* opcode information. Currently, there are no
|
|
|
|
* extended opcodes with a length greater than 1.
|
|
|
|
* \returns Exteded opcode length, in DWORDs
|
|
|
|
*/
|
|
|
|
uint32_t length() const {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Checks whether there are additional modifiers
|
|
|
|
* \returns \c true if the extended opcode is extended
|
|
|
|
*/
|
|
|
|
bool isExtended() const {
|
|
|
|
return !!bit::extract(m_token, 31, 31);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
uint32_t m_token = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Operand token
|
|
|
|
*
|
|
|
|
* Stores general information about one operand of an
|
|
|
|
* instruction. Like opcode tokens, operand tokens may
|
|
|
|
* be extended.
|
|
|
|
*/
|
|
|
|
class DxbcOperandToken {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcOperandToken(uint32_t token)
|
|
|
|
: m_token(token) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Number of operand components
|
|
|
|
*
|
|
|
|
* The number of components that the operand
|
|
|
|
* has. Can be zero, one, or four.
|
|
|
|
* \returns Number of components
|
|
|
|
*/
|
2017-11-01 00:01:40 +01:00
|
|
|
uint32_t numComponents() const {
|
2017-12-13 15:32:54 +01:00
|
|
|
std::array<uint32_t, 4> count = { 0, 1, 4, 0 };
|
2017-11-01 00:01:40 +01:00
|
|
|
return count.at(bit::extract(m_token, 0, 1));
|
2017-10-21 17:58:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Component selection mode
|
|
|
|
*
|
|
|
|
* Operands can be either masked so that some components
|
|
|
|
* will not be used, or they can be swizzled so that only
|
|
|
|
* a given set of components is used.
|
|
|
|
* \returns Component selection mode
|
|
|
|
*/
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcRegMode selectionMode() const {
|
|
|
|
return static_cast<DxbcRegMode>(
|
2017-10-21 17:58:58 +02:00
|
|
|
bit::extract(m_token, 2, 3));
|
|
|
|
}
|
|
|
|
|
2017-11-01 00:01:40 +01:00
|
|
|
/**
|
|
|
|
* \brief Component mask
|
|
|
|
*
|
2017-12-14 12:53:53 +01:00
|
|
|
* Used when the component selection
|
|
|
|
* mode is \c DxbcRegMode::Mask.
|
2017-12-13 15:32:54 +01:00
|
|
|
* \returns The component mask
|
|
|
|
*/
|
|
|
|
DxbcRegMask mask() const {
|
|
|
|
return DxbcRegMask(bit::extract(m_token, 4, 7));
|
|
|
|
}
|
|
|
|
|
2017-11-01 00:01:40 +01:00
|
|
|
/**
|
|
|
|
* \brief Component swizzle
|
|
|
|
*
|
2017-12-14 12:53:53 +01:00
|
|
|
* Used when the component selection
|
|
|
|
* mode is \c DxbcRegMode::Swizzle.
|
2017-12-13 15:32:54 +01:00
|
|
|
* \returns The component swizzle
|
|
|
|
*/
|
|
|
|
DxbcRegSwizzle swizzle() const {
|
|
|
|
return DxbcRegSwizzle(
|
|
|
|
bit::extract(m_token, 4, 5),
|
|
|
|
bit::extract(m_token, 6, 7),
|
|
|
|
bit::extract(m_token, 8, 9),
|
|
|
|
bit::extract(m_token, 10, 11));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Single component selection
|
2017-12-14 12:53:53 +01:00
|
|
|
*
|
|
|
|
* Used when the component selection
|
|
|
|
* mode is \c DxbcRegMode::Select1.
|
2017-12-13 15:32:54 +01:00
|
|
|
* \returns The component index
|
|
|
|
*/
|
|
|
|
uint32_t select1() const {
|
|
|
|
return bit::extract(m_token, 4, 5);
|
|
|
|
}
|
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
/**
|
|
|
|
* \brief Operand type
|
|
|
|
*
|
|
|
|
* Selects the type of the operand, i.e. whether the
|
|
|
|
* operand is a temporary register, a shader resource
|
|
|
|
* or a builtin interface variable.
|
|
|
|
* \returns Operand type
|
|
|
|
*/
|
|
|
|
DxbcOperandType type() const {
|
|
|
|
return static_cast<DxbcOperandType>(
|
|
|
|
bit::extract(m_token, 12, 19));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Index dimension
|
|
|
|
*
|
|
|
|
* Number of indices. In DXBC, each register file has
|
|
|
|
* a dimensionality, e.g. the temporary registers are
|
|
|
|
* one-dimensional and therefore require one index.
|
|
|
|
* \returns Number of index dimensions
|
|
|
|
*/
|
|
|
|
uint32_t indexDimension() const {
|
|
|
|
return bit::extract(m_token, 20, 21);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Index representation
|
|
|
|
*
|
|
|
|
* Stores whether an index is stored as an
|
|
|
|
* immediate value or as a relative value
|
|
|
|
* which requires another operand token.
|
|
|
|
* \param [in] dim Index dimension to query
|
|
|
|
* \returns Representation of that index
|
|
|
|
*/
|
|
|
|
DxbcOperandIndexRepresentation indexRepresentation(uint32_t dim) const {
|
|
|
|
return static_cast<DxbcOperandIndexRepresentation>(
|
|
|
|
bit::extract(m_token, 22 + 3 * dim, 24 + 3 * dim));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Checks whether the operand is extended
|
|
|
|
*
|
|
|
|
* Operands can be modified with extended tokens.
|
|
|
|
* \returns \c true if the operand is extended
|
|
|
|
*/
|
|
|
|
bool isExtended() const {
|
|
|
|
return !!bit::extract(m_token, 31, 31);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
uint32_t m_token = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Extended operand token
|
|
|
|
*
|
|
|
|
* Stores additional properties for an operand that
|
|
|
|
* cannot be stored in the initial operand token.
|
|
|
|
*/
|
|
|
|
class DxbcOperandTokenExt {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcOperandTokenExt() { }
|
|
|
|
DxbcOperandTokenExt(uint32_t token)
|
|
|
|
: m_token(token) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Operand extension type
|
|
|
|
* \returns Operand extension type
|
|
|
|
*/
|
|
|
|
DxbcOperandExt type() const {
|
|
|
|
return static_cast<DxbcOperandExt>(
|
|
|
|
bit::extract(m_token, 0, 5));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Data flags
|
|
|
|
* \returns Data flags
|
|
|
|
*/
|
|
|
|
uint32_t data() const {
|
|
|
|
return bit::extract(m_token, 6, 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Checks whether the operand is extended
|
|
|
|
*
|
|
|
|
* Like extended opcode tokens, extended
|
|
|
|
* operand tokens can be chained.
|
|
|
|
* \returns \c true if extended
|
|
|
|
*/
|
|
|
|
bool isExtended() const {
|
|
|
|
return !!bit::extract(m_token, 31, 31);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
uint32_t m_token = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief DXBC code DxbcCodeReader
|
2017-10-21 17:58:58 +02:00
|
|
|
*
|
2017-10-25 13:49:13 +02:00
|
|
|
* Helper class that can read DWORDs from a sized slice.
|
|
|
|
* Returns undefined numbers on out-of-bounds access, but
|
|
|
|
* makes sure not to access memory locations outside the
|
|
|
|
* original code array.
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-25 13:49:13 +02:00
|
|
|
class DxbcCodeReader {
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcCodeReader() { }
|
|
|
|
DxbcCodeReader(
|
2017-10-21 17:58:58 +02:00
|
|
|
const uint32_t* code,
|
2017-10-25 13:49:13 +02:00
|
|
|
uint32_t size)
|
|
|
|
: m_code(size != 0 ? code : nullptr),
|
|
|
|
m_size(size) { }
|
2017-10-21 17:58:58 +02:00
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
uint32_t getWord(uint32_t id) const {
|
|
|
|
return id < m_size ? m_code[id] : 0;
|
|
|
|
}
|
2017-10-21 17:58:58 +02:00
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcCodeReader& operator ++ ();
|
|
|
|
DxbcCodeReader& operator += (uint32_t n);
|
|
|
|
DxbcCodeReader operator + (uint32_t n) const;
|
|
|
|
|
|
|
|
bool operator == (const DxbcCodeReader& other) const;
|
|
|
|
bool operator != (const DxbcCodeReader& other) const;
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
const uint32_t* m_code = nullptr;
|
|
|
|
uint32_t m_size = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
/**
|
|
|
|
* \brief DXBC operand index
|
|
|
|
*
|
|
|
|
* Represents an index into an indexable register file.
|
|
|
|
* For each register file dimension, one operand index
|
|
|
|
* must be read from the encoded instruction.
|
|
|
|
*/
|
|
|
|
class DxbcOperandIndex {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcOperandIndex() { }
|
|
|
|
DxbcOperandIndex(
|
|
|
|
const DxbcCodeReader& code,
|
|
|
|
DxbcOperandIndexRepresentation rep)
|
|
|
|
: m_code(code), m_rep(rep) { }
|
|
|
|
|
|
|
|
uint32_t length() const;
|
|
|
|
|
|
|
|
bool hasImmPart() const;
|
|
|
|
bool hasRelPart() const;
|
|
|
|
|
|
|
|
uint64_t immPart() const;
|
|
|
|
DxbcOperand relPart() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
DxbcCodeReader m_code;
|
|
|
|
DxbcOperandIndexRepresentation m_rep;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief DXBC operand
|
2017-10-21 17:58:58 +02:00
|
|
|
*
|
2017-10-25 13:49:13 +02:00
|
|
|
* Provides methods to query the operand token
|
|
|
|
* including extended operand tokens, which may
|
|
|
|
* modify the operand's return value.
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-25 13:49:13 +02:00
|
|
|
class DxbcOperand {
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcOperand() { }
|
|
|
|
DxbcOperand(const DxbcCodeReader& code);
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Operand token
|
|
|
|
* \returns Operand token
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcOperandToken token() const {
|
|
|
|
return DxbcOperandToken(m_info.getWord(0));
|
2017-10-21 17:58:58 +02:00
|
|
|
}
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
/**
|
|
|
|
* \brief Operand length, in DWORDs
|
|
|
|
* \returns Number of DWORDs
|
|
|
|
*/
|
|
|
|
uint32_t length() const {
|
|
|
|
return m_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Operand index for a single dimension
|
|
|
|
*
|
|
|
|
* \param [in] dim Dimension to query
|
|
|
|
* \returns Operand index
|
|
|
|
*/
|
|
|
|
DxbcOperandIndex index(uint32_t dim) const;
|
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Queries an operand extension
|
|
|
|
*
|
|
|
|
* If an extended operand token with the given
|
|
|
|
* operand extension exists, return that token.
|
|
|
|
* \param [in] ext The operand extension
|
2017-12-12 13:00:37 +01:00
|
|
|
* \param [out] token The extended token
|
|
|
|
* \returns \c true if the token was defined
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-12-12 13:00:37 +01:00
|
|
|
bool queryOperandExt(
|
|
|
|
DxbcOperandExt ext,
|
|
|
|
DxbcOperandTokenExt& token) const;
|
2017-10-21 17:58:58 +02:00
|
|
|
|
2017-11-01 00:01:40 +01:00
|
|
|
/**
|
|
|
|
* \brief Reads 32-bit immediate integer
|
|
|
|
*
|
|
|
|
* \param [in] idx Component index
|
|
|
|
* \returns The immediate operand
|
|
|
|
*/
|
|
|
|
uint32_t imm32(uint32_t idx) const {
|
|
|
|
return m_data.getWord(idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Reads 64-bit immediate integer
|
|
|
|
*
|
|
|
|
* \param [in] idx Component index
|
|
|
|
* \returns The immediate operand
|
|
|
|
*/
|
|
|
|
uint64_t imm64(uint32_t idx) const {
|
|
|
|
uint64_t hi = m_data.getWord(2 * idx + 0);
|
|
|
|
uint64_t lo = m_data.getWord(2 * idx + 1);
|
|
|
|
return (hi << 32) | (lo);
|
|
|
|
}
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
private:
|
|
|
|
|
|
|
|
DxbcCodeReader m_info;
|
|
|
|
DxbcCodeReader m_data;
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
uint32_t m_length = 0;
|
|
|
|
std::array<uint32_t, 3> m_indexOffsets = { 0, 0, 0 };
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief DXBC instruction
|
|
|
|
*
|
|
|
|
* Provides methods to query the opcode token
|
|
|
|
* including extended opcode tokens, as well
|
|
|
|
* as convenience methods to read operands.
|
|
|
|
*/
|
|
|
|
class DxbcInstruction {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcInstruction() { }
|
|
|
|
DxbcInstruction(const DxbcCodeReader& code);
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Opcode token
|
|
|
|
* \returns Opcode token
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcOpcodeToken token() const {
|
|
|
|
return DxbcOpcodeToken(m_op.getWord(0));
|
2017-10-21 17:58:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Instruction length, in DWORDs
|
|
|
|
* \returns Instruction length, in DWORDs
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-25 13:49:13 +02:00
|
|
|
uint32_t length() const;
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Queries an opcode extension
|
|
|
|
*
|
|
|
|
* If an extended opcode token with the given
|
|
|
|
* opcode exists, the token will be returned.
|
2017-12-12 13:00:37 +01:00
|
|
|
* \param [in] extOpcode Extended opcode
|
|
|
|
* \param [out] token The extended token
|
|
|
|
* \returns \c true if the token was defined
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-12-12 13:00:37 +01:00
|
|
|
bool queryOpcodeExt(
|
|
|
|
DxbcExtOpcode extOpcode,
|
|
|
|
DxbcOpcodeTokenExt& token) const;
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Retrieves argument word
|
|
|
|
*
|
|
|
|
* Instruction arguments immediately follow the opcode
|
|
|
|
* tokens, including the extended opcodes. Argument 0
|
|
|
|
* will therefore be the first DWORD that is part of
|
|
|
|
* an instruction operand or an immediate number.
|
|
|
|
* \param [in] idx Argument word index
|
|
|
|
* \returns The word at the given index
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-26 16:32:10 +02:00
|
|
|
uint32_t arg(uint32_t idx) const {
|
2017-10-25 13:49:13 +02:00
|
|
|
return m_args.getWord(idx);
|
2017-10-21 17:58:58 +02:00
|
|
|
}
|
|
|
|
|
2017-11-13 00:22:52 +01:00
|
|
|
/**
|
|
|
|
* \brief Reads an argument enum
|
|
|
|
*
|
|
|
|
* Casts the word at the given location to an enum.
|
|
|
|
* Some instructions take name tokens as operands.
|
|
|
|
* \param [in] idx Argument word index
|
|
|
|
* \returns The enum value of the given word
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
T readEnum(uint32_t idx) const {
|
|
|
|
return static_cast<T>(arg(idx));
|
|
|
|
}
|
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
/**
|
2017-10-25 13:49:13 +02:00
|
|
|
* \brief Retrieves an operand
|
|
|
|
*
|
|
|
|
* \param [in] idx Argument word index
|
|
|
|
* \returns The operand object
|
2017-10-21 17:58:58 +02:00
|
|
|
*/
|
2017-10-26 16:32:10 +02:00
|
|
|
DxbcOperand operand(uint32_t idx) const {
|
2017-10-25 13:49:13 +02:00
|
|
|
return DxbcOperand(m_args + idx);
|
2017-10-21 17:58:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcCodeReader m_op;
|
|
|
|
DxbcCodeReader m_args;
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief DXBC instruction decoder
|
|
|
|
*
|
|
|
|
* Iterator that walks over DXBC instructions.
|
|
|
|
* Instruction boundaries are easy to find as
|
|
|
|
* the length of each instruction is encoded
|
|
|
|
* in the opcode token, much like in SPIR-V.
|
|
|
|
*/
|
|
|
|
class DxbcDecoder {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxbcDecoder() { }
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcDecoder(const uint32_t* code, uint32_t size)
|
|
|
|
: m_code(code, size) { }
|
2017-10-21 17:58:58 +02:00
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcDecoder& operator ++ () {
|
|
|
|
m_code += DxbcInstruction(m_code).length();
|
|
|
|
return *this;
|
|
|
|
}
|
2017-10-21 17:58:58 +02:00
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcInstruction operator * () const {
|
|
|
|
return DxbcInstruction(m_code);
|
|
|
|
}
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
bool operator == (const DxbcDecoder& other) const { return m_code == other.m_code; }
|
|
|
|
bool operator != (const DxbcDecoder& other) const { return m_code != other.m_code; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
DxbcCodeReader m_code;
|
2017-10-21 17:58:58 +02:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|