More style cleanup.
This commit is contained in:
parent
e6461f326c
commit
5e08889d93
|
@ -22,7 +22,7 @@ DEFINE_string(target, "", "Specifies the target .xex or .iso to execute.");
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
int xenia_main(std::vector<std::wstring>& args) {
|
int xenia_main(const std::vector<std::wstring>& args) {
|
||||||
Profiler::Initialize();
|
Profiler::Initialize();
|
||||||
Profiler::ThreadEnter("main");
|
Profiler::ThreadEnter("main");
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,13 @@
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
|
||||||
using namespace xe;
|
namespace xe {
|
||||||
using namespace xe::apu;
|
namespace apu {
|
||||||
using namespace xe::cpu;
|
|
||||||
|
|
||||||
AudioDriver::AudioDriver(Emulator* emulator)
|
AudioDriver::AudioDriver(Emulator* emulator)
|
||||||
: emulator_(emulator), memory_(emulator->memory()) {}
|
: emulator_(emulator), memory_(emulator->memory()) {}
|
||||||
|
|
||||||
AudioDriver::~AudioDriver() {}
|
AudioDriver::~AudioDriver() = default;
|
||||||
|
|
||||||
|
} // namespace apu
|
||||||
|
} // namespace xe
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace apu {
|
||||||
|
|
||||||
class AudioDriver {
|
class AudioDriver {
|
||||||
public:
|
public:
|
||||||
AudioDriver(Emulator* emulator);
|
explicit AudioDriver(Emulator* emulator);
|
||||||
virtual ~AudioDriver();
|
virtual ~AudioDriver();
|
||||||
|
|
||||||
virtual void SubmitFrame(uint32_t samples_ptr) = 0;
|
virtual void SubmitFrame(uint32_t samples_ptr) = 0;
|
||||||
|
|
|
@ -48,7 +48,7 @@ class AudioSystem {
|
||||||
void SubmitFrame(size_t index, uint32_t samples_ptr);
|
void SubmitFrame(size_t index, uint32_t samples_ptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AudioSystem(Emulator* emulator);
|
explicit AudioSystem(Emulator* emulator);
|
||||||
|
|
||||||
virtual void Initialize();
|
virtual void Initialize();
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace nop {
|
||||||
|
|
||||||
class NopAudioSystem : public AudioSystem {
|
class NopAudioSystem : public AudioSystem {
|
||||||
public:
|
public:
|
||||||
NopAudioSystem(Emulator* emulator);
|
explicit NopAudioSystem(Emulator* emulator);
|
||||||
~NopAudioSystem() override;
|
~NopAudioSystem() override;
|
||||||
|
|
||||||
static std::unique_ptr<AudioSystem> Create(Emulator* emulator);
|
static std::unique_ptr<AudioSystem> Create(Emulator* emulator);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
// Must be included before xaudio2.h so we get the right windows.h include.
|
// Must be included before xaudio2.h so we get the right windows.h include.
|
||||||
#include "xenia/base/platform_win.h"
|
#include "xenia/base/platform_win.h"
|
||||||
#include <xaudio2.h>
|
#include <xaudio2.h> // NOLINT(build/include_order)
|
||||||
|
|
||||||
#include "xenia/apu/apu_flags.h"
|
#include "xenia/apu/apu_flags.h"
|
||||||
#include "xenia/base/clock.h"
|
#include "xenia/base/clock.h"
|
||||||
|
@ -24,7 +24,8 @@ namespace xaudio2 {
|
||||||
|
|
||||||
class XAudio2AudioDriver::VoiceCallback : public IXAudio2VoiceCallback {
|
class XAudio2AudioDriver::VoiceCallback : public IXAudio2VoiceCallback {
|
||||||
public:
|
public:
|
||||||
VoiceCallback(xe::threading::Semaphore* semaphore) : semaphore_(semaphore) {}
|
explicit VoiceCallback(xe::threading::Semaphore* semaphore)
|
||||||
|
: semaphore_(semaphore) {}
|
||||||
~VoiceCallback() {}
|
~VoiceCallback() {}
|
||||||
|
|
||||||
void OnStreamEnd() {}
|
void OnStreamEnd() {}
|
||||||
|
@ -52,15 +53,10 @@ XAudio2AudioDriver::XAudio2AudioDriver(Emulator* emulator,
|
||||||
XAudio2AudioDriver::~XAudio2AudioDriver() = default;
|
XAudio2AudioDriver::~XAudio2AudioDriver() = default;
|
||||||
|
|
||||||
const DWORD ChannelMasks[] = {
|
const DWORD ChannelMasks[] = {
|
||||||
0, // TODO: fixme
|
0, 0, SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY, 0,
|
||||||
0, // TODO: fixme
|
0, 0, SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT |
|
||||||
SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY,
|
SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
|
||||||
0, // TODO: fixme
|
0,
|
||||||
0, // TODO: fixme
|
|
||||||
0, // TODO: fixme
|
|
||||||
SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT |
|
|
||||||
SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
|
|
||||||
0, // TODO: fixme
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void XAudio2AudioDriver::Initialize() {
|
void XAudio2AudioDriver::Initialize() {
|
||||||
|
@ -152,7 +148,7 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) {
|
||||||
|
|
||||||
XAUDIO2_BUFFER buffer;
|
XAUDIO2_BUFFER buffer;
|
||||||
buffer.Flags = 0;
|
buffer.Flags = 0;
|
||||||
buffer.pAudioData = (BYTE*)output_frame;
|
buffer.pAudioData = reinterpret_cast<BYTE*>(output_frame);
|
||||||
buffer.AudioBytes = frame_size_;
|
buffer.AudioBytes = frame_size_;
|
||||||
buffer.PlayBegin = 0;
|
buffer.PlayBegin = 0;
|
||||||
buffer.PlayLength = channel_samples_;
|
buffer.PlayLength = channel_samples_;
|
||||||
|
@ -171,7 +167,8 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) {
|
||||||
|
|
||||||
// Update playback ratio to our time scalar.
|
// Update playback ratio to our time scalar.
|
||||||
// This will keep audio in sync with the game clock.
|
// This will keep audio in sync with the game clock.
|
||||||
pcm_voice_->SetFrequencyRatio(float(xe::Clock::guest_time_scalar()));
|
pcm_voice_->SetFrequencyRatio(
|
||||||
|
static_cast<float>(xe::Clock::guest_time_scalar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void XAudio2AudioDriver::Shutdown() {
|
void XAudio2AudioDriver::Shutdown() {
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace xaudio2 {
|
||||||
|
|
||||||
class XAudio2AudioSystem : public AudioSystem {
|
class XAudio2AudioSystem : public AudioSystem {
|
||||||
public:
|
public:
|
||||||
XAudio2AudioSystem(Emulator* emulator);
|
explicit XAudio2AudioSystem(Emulator* emulator);
|
||||||
~XAudio2AudioSystem() override;
|
~XAudio2AudioSystem() override;
|
||||||
|
|
||||||
static std::unique_ptr<AudioSystem> Create(Emulator* emulator);
|
static std::unique_ptr<AudioSystem> Create(Emulator* emulator);
|
||||||
|
|
|
@ -8,13 +8,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/apu/xma_context.h"
|
#include "xenia/apu/xma_context.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "xenia/apu/xma_decoder.h"
|
#include "xenia/apu/xma_decoder.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/ring_buffer.h"
|
#include "xenia/base/ring_buffer.h"
|
||||||
#include "xenia/profiling.h"
|
#include "xenia/profiling.h"
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "libavcodec/avcodec.h"
|
#include "libavcodec/avcodec.h"
|
||||||
#include "libavutil/channel_layout.h"
|
#include "libavutil/channel_layout.h"
|
||||||
|
@ -54,7 +56,7 @@ int XmaContext::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) {
|
||||||
avcodec_initialized = true;
|
avcodec_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate important stuff
|
// Allocate important stuff.
|
||||||
codec_ = avcodec_find_decoder(AV_CODEC_ID_WMAPRO);
|
codec_ = avcodec_find_decoder(AV_CODEC_ID_WMAPRO);
|
||||||
if (!codec_) {
|
if (!codec_) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -78,14 +80,14 @@ int XmaContext::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) {
|
||||||
context_->sample_rate = 0;
|
context_->sample_rate = 0;
|
||||||
context_->block_align = kBytesPerPacket;
|
context_->block_align = kBytesPerPacket;
|
||||||
|
|
||||||
// Extra data passed to the decoder
|
// Extra data passed to the decoder.
|
||||||
std::memset(&extra_data_, 0, sizeof(extra_data_));
|
std::memset(&extra_data_, 0, sizeof(extra_data_));
|
||||||
extra_data_.bits_per_sample = 16;
|
extra_data_.bits_per_sample = 16;
|
||||||
extra_data_.channel_mask = AV_CH_FRONT_RIGHT;
|
extra_data_.channel_mask = AV_CH_FRONT_RIGHT;
|
||||||
extra_data_.decode_flags = 0x10D6;
|
extra_data_.decode_flags = 0x10D6;
|
||||||
|
|
||||||
context_->extradata_size = sizeof(extra_data_);
|
context_->extradata_size = sizeof(extra_data_);
|
||||||
context_->extradata = (uint8_t*)&extra_data_;
|
context_->extradata = reinterpret_cast<uint8_t*>(&extra_data_);
|
||||||
|
|
||||||
// Current frame stuff whatever
|
// Current frame stuff whatever
|
||||||
// samples per frame * 2 max channels * output bytes
|
// samples per frame * 2 max channels * output bytes
|
||||||
|
@ -107,7 +109,7 @@ void XmaContext::Work() {
|
||||||
|
|
||||||
auto context_ptr = memory()->TranslateVirtual(guest_ptr());
|
auto context_ptr = memory()->TranslateVirtual(guest_ptr());
|
||||||
XMA_CONTEXT_DATA data(context_ptr);
|
XMA_CONTEXT_DATA data(context_ptr);
|
||||||
DecodePackets(data);
|
DecodePackets(&data);
|
||||||
data.Store(context_ptr);
|
data.Store(context_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +167,7 @@ void XmaContext::Disable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmaContext::Release() {
|
void XmaContext::Release() {
|
||||||
// Lock it in case the decoder thread is working on it now
|
// Lock it in case the decoder thread is working on it now.
|
||||||
std::lock_guard<xe::mutex> lock(lock_);
|
std::lock_guard<xe::mutex> lock(lock_);
|
||||||
assert_true(is_allocated_ == true);
|
assert_true(is_allocated_ == true);
|
||||||
|
|
||||||
|
@ -191,7 +193,7 @@ int XmaContext::GetSampleRate(int id) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) {
|
||||||
SCOPE_profile_cpu_f("apu");
|
SCOPE_profile_cpu_f("apu");
|
||||||
|
|
||||||
// What I see:
|
// What I see:
|
||||||
|
@ -215,25 +217,26 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
// SPUs also support stereo decoding. (data.is_stereo)
|
// SPUs also support stereo decoding. (data.is_stereo)
|
||||||
|
|
||||||
// Quick die if there's no data.
|
// Quick die if there's no data.
|
||||||
if (!data.input_buffer_0_valid && !data.input_buffer_1_valid) {
|
if (!data->input_buffer_0_valid && !data->input_buffer_1_valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the output buffer - we cannot decode anything else if it's
|
// Check the output buffer - we cannot decode anything else if it's
|
||||||
// unavailable.
|
// unavailable.
|
||||||
if (!data.output_buffer_valid) {
|
if (!data->output_buffer_valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output buffers are in raw PCM samples, 256 bytes per block.
|
// Output buffers are in raw PCM samples, 256 bytes per block.
|
||||||
// Output buffer is a ring buffer. We need to write from the write offset
|
// Output buffer is a ring buffer. We need to write from the write offset
|
||||||
// to the read offset.
|
// to the read offset.
|
||||||
uint8_t* output_buffer = memory()->TranslatePhysical(data.output_buffer_ptr);
|
uint8_t* output_buffer = memory()->TranslatePhysical(data->output_buffer_ptr);
|
||||||
uint32_t output_capacity = data.output_buffer_block_count * kBytesPerSubframe;
|
uint32_t output_capacity =
|
||||||
|
data->output_buffer_block_count * kBytesPerSubframe;
|
||||||
uint32_t output_read_offset =
|
uint32_t output_read_offset =
|
||||||
data.output_buffer_read_offset * kBytesPerSubframe;
|
data->output_buffer_read_offset * kBytesPerSubframe;
|
||||||
uint32_t output_write_offset =
|
uint32_t output_write_offset =
|
||||||
data.output_buffer_write_offset * kBytesPerSubframe;
|
data->output_buffer_write_offset * kBytesPerSubframe;
|
||||||
|
|
||||||
RingBuffer output_rb(output_buffer, output_capacity);
|
RingBuffer output_rb(output_buffer, output_capacity);
|
||||||
output_rb.set_read_offset(output_read_offset);
|
output_rb.set_read_offset(output_read_offset);
|
||||||
|
@ -245,7 +248,7 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
while (output_remaining_bytes > 0) {
|
while (output_remaining_bytes > 0) {
|
||||||
// This'll copy audio samples into the output buffer.
|
// This'll copy audio samples into the output buffer.
|
||||||
// The samples need to be 2 bytes long!
|
// The samples need to be 2 bytes long!
|
||||||
// Copies one frame at a time, so keep calling this until size == 0
|
// Copies one frame at a time, so keep calling this until size == 0.
|
||||||
int written_bytes = 0;
|
int written_bytes = 0;
|
||||||
int decode_attempts_remaining = 3;
|
int decode_attempts_remaining = 3;
|
||||||
|
|
||||||
|
@ -278,7 +281,7 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
-written_bytes);
|
-written_bytes);
|
||||||
|
|
||||||
// Failed out.
|
// Failed out.
|
||||||
if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
|
if (data->input_buffer_0_valid || data->input_buffer_1_valid) {
|
||||||
// There's new data available - maybe we'll be ok if we decode it?
|
// There's new data available - maybe we'll be ok if we decode it?
|
||||||
written_bytes = 0;
|
written_bytes = 0;
|
||||||
DiscardPacket();
|
DiscardPacket();
|
||||||
|
@ -288,20 +291,20 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.output_buffer_write_offset = output_rb.write_offset() / 256;
|
data->output_buffer_write_offset = output_rb.write_offset() / 256;
|
||||||
output_remaining_bytes -= written_bytes;
|
output_remaining_bytes -= written_bytes;
|
||||||
|
|
||||||
// If we need more data and the input buffers have it, grab it.
|
// If we need more data and the input buffers have it, grab it.
|
||||||
if (written_bytes) {
|
if (written_bytes) {
|
||||||
// Haven't finished with current packet.
|
// Haven't finished with current packet.
|
||||||
continue;
|
continue;
|
||||||
} else if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
|
} else if (data->input_buffer_0_valid || data->input_buffer_1_valid) {
|
||||||
// Done with previous packet, so grab a new one.
|
// Done with previous packet, so grab a new one.
|
||||||
int ret = StartPacket(data);
|
int ret = StartPacket(data);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
// No more data (but may have prepared a packet)
|
// No more data (but may have prepared a packet)
|
||||||
data.input_buffer_0_valid = 0;
|
data->input_buffer_0_valid = 0;
|
||||||
data.input_buffer_1_valid = 0;
|
data->input_buffer_1_valid = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Decoder is out of data and there's no more to give.
|
// Decoder is out of data and there's no more to give.
|
||||||
|
@ -310,27 +313,29 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The game will kick us again with a new output buffer later.
|
// The game will kick us again with a new output buffer later.
|
||||||
data.output_buffer_valid = 0;
|
data->output_buffer_valid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int XmaContext::StartPacket(XMA_CONTEXT_DATA& data) {
|
int XmaContext::StartPacket(XMA_CONTEXT_DATA* data) {
|
||||||
// Translate pointers for future use.
|
// Translate pointers for future use.
|
||||||
uint8_t* in0 = data.input_buffer_0_valid
|
uint8_t* in0 = data->input_buffer_0_valid
|
||||||
? memory()->TranslatePhysical(data.input_buffer_0_ptr)
|
? memory()->TranslatePhysical(data->input_buffer_0_ptr)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
uint8_t* in1 = data.input_buffer_1_valid
|
uint8_t* in1 = data->input_buffer_1_valid
|
||||||
? memory()->TranslatePhysical(data.input_buffer_1_ptr)
|
? memory()->TranslatePhysical(data->input_buffer_1_ptr)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
int sample_rate = GetSampleRate(data.sample_rate);
|
int sample_rate = GetSampleRate(data->sample_rate);
|
||||||
int channels = data.is_stereo ? 2 : 1;
|
int channels = data->is_stereo ? 2 : 1;
|
||||||
|
|
||||||
// See if we've finished with the input.
|
// See if we've finished with the input.
|
||||||
// Block count is in packets, so expand by packet size.
|
// Block count is in packets, so expand by packet size.
|
||||||
uint32_t input_size_0_bytes =
|
uint32_t input_size_0_bytes = data->input_buffer_0_valid
|
||||||
data.input_buffer_0_valid ? (data.input_buffer_0_packet_count) * 2048 : 0;
|
? (data->input_buffer_0_packet_count) * 2048
|
||||||
uint32_t input_size_1_bytes =
|
: 0;
|
||||||
data.input_buffer_1_valid ? (data.input_buffer_1_packet_count) * 2048 : 0;
|
uint32_t input_size_1_bytes = data->input_buffer_1_valid
|
||||||
|
? (data->input_buffer_1_packet_count) * 2048
|
||||||
|
: 0;
|
||||||
|
|
||||||
// Total input size
|
// Total input size
|
||||||
uint32_t input_size_bytes = input_size_0_bytes + input_size_1_bytes;
|
uint32_t input_size_bytes = input_size_0_bytes + input_size_1_bytes;
|
||||||
|
@ -338,7 +343,7 @@ int XmaContext::StartPacket(XMA_CONTEXT_DATA& data) {
|
||||||
// Input read offset is in bits. Typically starts at 32 (4 bytes).
|
// Input read offset is in bits. Typically starts at 32 (4 bytes).
|
||||||
// "Sequence" offset - used internally for WMA Pro decoder.
|
// "Sequence" offset - used internally for WMA Pro decoder.
|
||||||
// Just the read offset.
|
// Just the read offset.
|
||||||
uint32_t seq_offset_bytes = (data.input_buffer_read_offset & ~0x7FF) / 8;
|
uint32_t seq_offset_bytes = (data->input_buffer_read_offset & ~0x7FF) / 8;
|
||||||
uint32_t input_remaining_bytes = input_size_bytes - seq_offset_bytes;
|
uint32_t input_remaining_bytes = input_size_bytes - seq_offset_bytes;
|
||||||
|
|
||||||
if (seq_offset_bytes < input_size_bytes) {
|
if (seq_offset_bytes < input_size_bytes) {
|
||||||
|
@ -348,7 +353,7 @@ int XmaContext::StartPacket(XMA_CONTEXT_DATA& data) {
|
||||||
|
|
||||||
if (seq_offset_bytes >= input_size_0_bytes && input_size_1_bytes) {
|
if (seq_offset_bytes >= input_size_0_bytes && input_size_1_bytes) {
|
||||||
// Size overlap, select input buffer 1.
|
// Size overlap, select input buffer 1.
|
||||||
// TODO: This needs testing.
|
// TODO(DrChat): This needs testing.
|
||||||
input_offset_bytes -= input_size_0_bytes;
|
input_offset_bytes -= input_size_0_bytes;
|
||||||
input_buffer = in1;
|
input_buffer = in1;
|
||||||
}
|
}
|
||||||
|
@ -358,11 +363,11 @@ int XmaContext::StartPacket(XMA_CONTEXT_DATA& data) {
|
||||||
assert_true(input_offset_bytes % 2048 == 0);
|
assert_true(input_offset_bytes % 2048 == 0);
|
||||||
PreparePacket(packet, seq_offset_bytes, kBytesPerPacket, sample_rate,
|
PreparePacket(packet, seq_offset_bytes, kBytesPerPacket, sample_rate,
|
||||||
channels);
|
channels);
|
||||||
data.input_buffer_read_offset += kBytesPerPacket * 8;
|
data->input_buffer_read_offset += kBytesPerPacket * 8;
|
||||||
|
|
||||||
input_remaining_bytes -= kBytesPerPacket;
|
input_remaining_bytes -= kBytesPerPacket;
|
||||||
if (input_remaining_bytes <= 0) {
|
if (input_remaining_bytes <= 0) {
|
||||||
// Used the last of the data but prepared a packet
|
// Used the last of the data but prepared a packet.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -381,23 +386,24 @@ int XmaContext::PreparePacket(uint8_t* input, size_t seq_offset, size_t size,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (packet_->size > 0 || current_frame_pos_ != frame_samples_size_) {
|
if (packet_->size > 0 || current_frame_pos_ != frame_samples_size_) {
|
||||||
// Haven't finished parsing another packet
|
// Haven't finished parsing another packet.
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(packet_data_, input, size);
|
std::memcpy(packet_data_, input, size);
|
||||||
|
|
||||||
// Modify the packet header so it's WMAPro compatible
|
// Modify the packet header so it's WMAPro compatible.
|
||||||
*((int*)packet_data_) = (((seq_offset & 0x7800) | 0x400) >> 7) |
|
auto int_packet_data = reinterpret_cast<int*>(packet_data_);
|
||||||
(*((int*)packet_data_) & 0xFFFEFF08);
|
*int_packet_data =
|
||||||
|
(((seq_offset & 0x7800) | 0x400) >> 7) | (*int_packet_data & 0xFFFEFF08);
|
||||||
|
|
||||||
packet_->data = packet_data_;
|
packet_->data = packet_data_;
|
||||||
packet_->size = kBytesPerPacket;
|
packet_->size = kBytesPerPacket;
|
||||||
|
|
||||||
// Re-initialize the context with new sample rate and channels
|
// Re-initialize the context with new sample rate and channels.
|
||||||
if (context_->sample_rate != sample_rate || context_->channels != channels) {
|
if (context_->sample_rate != sample_rate || context_->channels != channels) {
|
||||||
// We have to reopen the codec so it'll realloc whatever data it needs.
|
// We have to reopen the codec so it'll realloc whatever data it needs.
|
||||||
// TODO: Find a better way.
|
// TODO(DrChat): Find a better way.
|
||||||
avcodec_close(context_);
|
avcodec_close(context_);
|
||||||
|
|
||||||
context_->sample_rate = sample_rate;
|
context_->sample_rate = sample_rate;
|
||||||
|
@ -444,11 +450,11 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
while (output_size > 0 && packet_->size > 0) {
|
while (output_size > 0 && packet_->size > 0) {
|
||||||
int got_frame = 0;
|
int got_frame = 0;
|
||||||
|
|
||||||
// Decode the current frame
|
// Decode the current frame.
|
||||||
int len =
|
int len =
|
||||||
avcodec_decode_audio4(context_, decoded_frame_, &got_frame, packet_);
|
avcodec_decode_audio4(context_, decoded_frame_, &got_frame, packet_);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
// Error in codec (bad sample rate or something)
|
// Error in codec (bad sample rate or something).
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,12 +462,12 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
*read_bytes += len;
|
*read_bytes += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset by decoded length
|
// Offset by decoded length.
|
||||||
packet_->size -= len;
|
packet_->size -= len;
|
||||||
packet_->data += len;
|
packet_->data += len;
|
||||||
packet_->dts = packet_->pts = AV_NOPTS_VALUE;
|
packet_->dts = packet_->pts = AV_NOPTS_VALUE;
|
||||||
|
|
||||||
// Successfully decoded a frame
|
// Successfully decoded a frame.
|
||||||
if (got_frame) {
|
if (got_frame) {
|
||||||
// Validity checks.
|
// Validity checks.
|
||||||
if (decoded_frame_->nb_samples > kSamplesPerFrame) {
|
if (decoded_frame_->nb_samples > kSamplesPerFrame) {
|
||||||
|
@ -470,7 +476,7 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the returned buffer size
|
// Check the returned buffer size.
|
||||||
if (av_samples_get_buffer_size(NULL, context_->channels,
|
if (av_samples_get_buffer_size(NULL, context_->channels,
|
||||||
decoded_frame_->nb_samples,
|
decoded_frame_->nb_samples,
|
||||||
context_->sample_fmt, 1) !=
|
context_->sample_fmt, 1) !=
|
||||||
|
@ -480,12 +486,12 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
|
|
||||||
// Loop through every sample, convert and drop it into the output array.
|
// Loop through every sample, convert and drop it into the output array.
|
||||||
// If more than one channel, the game wants the samples from each channel
|
// If more than one channel, the game wants the samples from each channel
|
||||||
// interleaved next to eachother
|
// interleaved next to each other.
|
||||||
uint32_t o = 0;
|
uint32_t o = 0;
|
||||||
for (int i = 0; i < decoded_frame_->nb_samples; i++) {
|
for (int i = 0; i < decoded_frame_->nb_samples; i++) {
|
||||||
for (int j = 0; j < context_->channels; j++) {
|
for (int j = 0; j < context_->channels; j++) {
|
||||||
// Select the appropriate array based on the current channel.
|
// Select the appropriate array based on the current channel.
|
||||||
float* sample_array = (float*)decoded_frame_->data[j];
|
auto sample_array = reinterpret_cast<float*>(decoded_frame_->data[j]);
|
||||||
|
|
||||||
// Raw sample should be within [-1, 1].
|
// Raw sample should be within [-1, 1].
|
||||||
// Clamp it, just in case.
|
// Clamp it, just in case.
|
||||||
|
@ -500,8 +506,8 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
}
|
}
|
||||||
current_frame_pos_ = 0;
|
current_frame_pos_ = 0;
|
||||||
|
|
||||||
// Total size of the frame's samples
|
// Total size of the frame's samples.
|
||||||
// Magic number 2 is sizeof an output sample
|
// Magic number 2 is sizeof an output sample.
|
||||||
frame_samples_size_ = context_->channels * decoded_frame_->nb_samples * 2;
|
frame_samples_size_ = context_->channels * decoded_frame_->nb_samples * 2;
|
||||||
|
|
||||||
to_copy = std::min(output_size, (size_t)(frame_samples_size_));
|
to_copy = std::min(output_size, (size_t)(frame_samples_size_));
|
||||||
|
@ -513,9 +519,9 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return number of bytes written
|
// Return number of bytes written.
|
||||||
return (int)(output_offset - original_offset);
|
return static_cast<int>(output_offset - original_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace xe
|
|
||||||
} // namespace apu
|
} // namespace apu
|
||||||
|
} // namespace xe
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct XMA_CONTEXT_DATA {
|
||||||
// DWORD 10-15
|
// DWORD 10-15
|
||||||
uint32_t unk_dwords_10_15[6]; // reserved?
|
uint32_t unk_dwords_10_15[6]; // reserved?
|
||||||
|
|
||||||
XMA_CONTEXT_DATA(const void* ptr) {
|
explicit XMA_CONTEXT_DATA(const void* ptr) {
|
||||||
xe::copy_and_swap(reinterpret_cast<uint32_t*>(this),
|
xe::copy_and_swap(reinterpret_cast<uint32_t*>(this),
|
||||||
reinterpret_cast<const uint32_t*>(ptr),
|
reinterpret_cast<const uint32_t*>(ptr),
|
||||||
sizeof(XMA_CONTEXT_DATA) / 4);
|
sizeof(XMA_CONTEXT_DATA) / 4);
|
||||||
|
@ -139,7 +139,7 @@ class XmaContext {
|
||||||
static const uint32_t kOutputBytesPerBlock = 256;
|
static const uint32_t kOutputBytesPerBlock = 256;
|
||||||
static const uint32_t kOutputMaxSizeBytes = 31 * kOutputBytesPerBlock;
|
static const uint32_t kOutputMaxSizeBytes = 31 * kOutputBytesPerBlock;
|
||||||
|
|
||||||
XmaContext();
|
explicit XmaContext();
|
||||||
~XmaContext();
|
~XmaContext();
|
||||||
|
|
||||||
int Setup(uint32_t id, Memory* memory, uint32_t guest_ptr);
|
int Setup(uint32_t id, Memory* memory, uint32_t guest_ptr);
|
||||||
|
@ -164,8 +164,8 @@ class XmaContext {
|
||||||
private:
|
private:
|
||||||
static int GetSampleRate(int id);
|
static int GetSampleRate(int id);
|
||||||
|
|
||||||
void DecodePackets(XMA_CONTEXT_DATA& data);
|
void DecodePackets(XMA_CONTEXT_DATA* data);
|
||||||
int StartPacket(XMA_CONTEXT_DATA& data);
|
int StartPacket(XMA_CONTEXT_DATA* data);
|
||||||
|
|
||||||
int PreparePacket(uint8_t* input, size_t seq_offset, size_t size,
|
int PreparePacket(uint8_t* input, size_t seq_offset, size_t size,
|
||||||
int sample_rate, int channels);
|
int sample_rate, int channels);
|
||||||
|
|
|
@ -50,8 +50,6 @@ extern "C" {
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace apu {
|
namespace apu {
|
||||||
|
|
||||||
using namespace xe::cpu;
|
|
||||||
|
|
||||||
XmaDecoder::XmaDecoder(Emulator* emulator)
|
XmaDecoder::XmaDecoder(Emulator* emulator)
|
||||||
: emulator_(emulator),
|
: emulator_(emulator),
|
||||||
memory_(emulator->memory()),
|
memory_(emulator->memory()),
|
||||||
|
@ -75,8 +73,8 @@ X_STATUS XmaDecoder::Setup() {
|
||||||
// Let the processor know we want register access callbacks.
|
// Let the processor know we want register access callbacks.
|
||||||
emulator_->memory()->AddVirtualMappedRange(
|
emulator_->memory()->AddVirtualMappedRange(
|
||||||
0x7FEA0000, 0xFFFF0000, 0x0000FFFF, this,
|
0x7FEA0000, 0xFFFF0000, 0x0000FFFF, this,
|
||||||
reinterpret_cast<MMIOReadCallback>(MMIOReadRegisterThunk),
|
reinterpret_cast<cpu::MMIOReadCallback>(MMIOReadRegisterThunk),
|
||||||
reinterpret_cast<MMIOWriteCallback>(MMIOWriteRegisterThunk));
|
reinterpret_cast<cpu::MMIOWriteCallback>(MMIOWriteRegisterThunk));
|
||||||
|
|
||||||
// Setup XMA context data.
|
// Setup XMA context data.
|
||||||
context_data_first_ptr_ = memory()->SystemHeapAlloc(
|
context_data_first_ptr_ = memory()->SystemHeapAlloc(
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "xenia/apu/xma_context.h"
|
||||||
#include "xenia/emulator.h"
|
#include "xenia/emulator.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
#include "xenia/apu/xma_context.h"
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
@ -31,8 +31,8 @@ struct XMA_CONTEXT_DATA;
|
||||||
|
|
||||||
class XmaDecoder {
|
class XmaDecoder {
|
||||||
public:
|
public:
|
||||||
XmaDecoder(Emulator* emulator);
|
explicit XmaDecoder(Emulator* emulator);
|
||||||
virtual ~XmaDecoder();
|
~XmaDecoder();
|
||||||
|
|
||||||
Emulator* emulator() const { return emulator_; }
|
Emulator* emulator() const { return emulator_; }
|
||||||
Memory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
|
|
||||||
#include "xenia/base/platform.h"
|
#include "xenia/base/platform.h"
|
||||||
|
|
||||||
#if XE_PLATFORM_MAC
|
|
||||||
#include <libkern/OSAtomic.h>
|
|
||||||
#elif XE_PLATFORM_WIN32
|
|
||||||
#include <intrin.h>
|
|
||||||
#endif // XE_PLATFORM_MAC
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
// These functions are modeled off of the Apple OSAtomic routines
|
// These functions are modeled off of the Apple OSAtomic routines
|
||||||
|
|
|
@ -77,8 +77,8 @@ inline T byte_swap(T value) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct be {
|
struct be {
|
||||||
be() = default;
|
be() = default;
|
||||||
be(const T& src) : value(xe::byte_swap(src)) {}
|
be(const T& src) : value(xe::byte_swap(src)) {} // NOLINT(runtime/explicit)
|
||||||
be(const be& other) { value = other.value; }
|
be(const be& other) { value = other.value; } // NOLINT(runtime/explicit)
|
||||||
operator T() const { return xe::byte_swap(value); }
|
operator T() const { return xe::byte_swap(value); }
|
||||||
|
|
||||||
be<T>& operator+=(int a) {
|
be<T>& operator+=(int a) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ bool has_console_attached();
|
||||||
struct EntryInfo {
|
struct EntryInfo {
|
||||||
std::wstring name;
|
std::wstring name;
|
||||||
std::wstring usage;
|
std::wstring usage;
|
||||||
int (*entry_point)(std::vector<std::wstring>& args);
|
int (*entry_point)(const std::vector<std::wstring>& args);
|
||||||
};
|
};
|
||||||
EntryInfo GetEntryInfo();
|
EntryInfo GetEntryInfo();
|
||||||
|
|
||||||
|
|
|
@ -64,10 +64,10 @@ int Main() {
|
||||||
|
|
||||||
// Convert all args to narrow, as gflags doesn't support wchar.
|
// Convert all args to narrow, as gflags doesn't support wchar.
|
||||||
int argca = argc;
|
int argca = argc;
|
||||||
char** argva = (char**)alloca(sizeof(char*) * argca);
|
char** argva = reinterpret_cast<char**>(alloca(sizeof(char*) * argca));
|
||||||
for (int n = 0; n < argca; n++) {
|
for (int n = 0; n < argca; n++) {
|
||||||
size_t len = wcslen(argv[n]);
|
size_t len = wcslen(argv[n]);
|
||||||
argva[n] = (char*)alloca(len + 1);
|
argva[n] = reinterpret_cast<char*>(alloca(len + 1));
|
||||||
wcstombs_s(nullptr, argva[n], len + 1, argv[n], _TRUNCATE);
|
wcstombs_s(nullptr, argva[n], len + 1, argv[n], _TRUNCATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,17 +110,17 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR command_line, int) {
|
||||||
#if defined _M_IX86
|
#if defined _M_IX86
|
||||||
#pragma comment( \
|
#pragma comment( \
|
||||||
linker, \
|
linker, \
|
||||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") // NOLINT(whitespace/line_length)
|
||||||
#elif defined _M_IA64
|
#elif defined _M_IA64
|
||||||
#pragma comment( \
|
#pragma comment( \
|
||||||
linker, \
|
linker, \
|
||||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") // NOLINT(whitespace/line_length)
|
||||||
#elif defined _M_X64
|
#elif defined _M_X64
|
||||||
#pragma comment( \
|
#pragma comment( \
|
||||||
linker, \
|
linker, \
|
||||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") // NOLINT(whitespace/line_length)
|
||||||
#else
|
#else
|
||||||
#pragma comment( \
|
#pragma comment( \
|
||||||
linker, \
|
linker, \
|
||||||
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // NOLINT(whitespace/line_length)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -86,7 +86,6 @@ std::unique_ptr<MappedMemory> MappedMemory::Open(const std::wstring& path,
|
||||||
|
|
||||||
mm->mapping_handle = CreateFileMapping(mm->file_handle, nullptr,
|
mm->mapping_handle = CreateFileMapping(mm->file_handle, nullptr,
|
||||||
mapping_protect, 0, 0, nullptr);
|
mapping_protect, 0, 0, nullptr);
|
||||||
//(DWORD)(aligned_length >> 32), (DWORD)(aligned_length & 0xFFFFFFFF), NULL);
|
|
||||||
if (!mm->mapping_handle) {
|
if (!mm->mapping_handle) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +155,7 @@ class Win32ChunkedMappedMemoryWriter : public ChunkedMappedMemoryWriter {
|
||||||
private:
|
private:
|
||||||
class Chunk {
|
class Chunk {
|
||||||
public:
|
public:
|
||||||
Chunk(size_t capacity)
|
explicit Chunk(size_t capacity)
|
||||||
: file_handle_(0),
|
: file_handle_(0),
|
||||||
mapping_handle_(0),
|
mapping_handle_(0),
|
||||||
data_(nullptr),
|
data_(nullptr),
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace xe {
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
uint16_t float_to_half(float value) {
|
uint16_t float_to_half(float value) {
|
||||||
uint32_t Result;
|
uint32_t Result;
|
||||||
uint32_t IValue = ((uint32_t*)(&value))[0];
|
uint32_t IValue = (reinterpret_cast<uint32_t*>(&value))[0];
|
||||||
uint32_t Sign = (IValue & 0x80000000U) >> 16U;
|
uint32_t Sign = (IValue & 0x80000000U) >> 16U;
|
||||||
IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
|
IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
|
||||||
if (IValue > 0x47FFEFFFU) {
|
if (IValue > 0x47FFEFFFU) {
|
||||||
|
@ -63,7 +63,7 @@ float half_to_float(uint16_t value) {
|
||||||
uint32_t Result = ((value & 0x8000) << 16) | // Sign
|
uint32_t Result = ((value & 0x8000) << 16) | // Sign
|
||||||
((Exponent + 112) << 23) | // Exponent
|
((Exponent + 112) << 23) | // Exponent
|
||||||
(Mantissa << 13); // Mantissa
|
(Mantissa << 13); // Mantissa
|
||||||
return *(float*)&Result;
|
return *reinterpret_cast<float*>(&Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -14,10 +14,11 @@
|
||||||
|
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
|
||||||
|
// winsock includes must come after platform_win.h:
|
||||||
#include "xenia/base/platform_win.h"
|
#include "xenia/base/platform_win.h"
|
||||||
#include <mstcpip.h> // NOLINT(must follow platform_win.h)
|
#include <mstcpip.h> // NOLINT(build/include_order)
|
||||||
#include <winsock2.h> // NOLINT(must follow platform_win.h)
|
#include <winsock2.h> // NOLINT(build/include_order)
|
||||||
#include <ws2tcpip.h> // NOLINT(must follow platform_win.h)
|
#include <ws2tcpip.h> // NOLINT(build/include_order)
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_ASSEMBLER_H_
|
#ifndef XENIA_CPU_BACKEND_ASSEMBLER_H_
|
||||||
#define XENIA_BACKEND_ASSEMBLER_H_
|
#define XENIA_CPU_BACKEND_ASSEMBLER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ class Backend;
|
||||||
|
|
||||||
class Assembler {
|
class Assembler {
|
||||||
public:
|
public:
|
||||||
Assembler(Backend* backend);
|
explicit Assembler(Backend* backend);
|
||||||
virtual ~Assembler();
|
virtual ~Assembler();
|
||||||
|
|
||||||
virtual bool Initialize();
|
virtual bool Initialize();
|
||||||
|
@ -49,4 +49,4 @@ class Assembler {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_ASSEMBLER_H_
|
#endif // XENIA_CPU_BACKEND_ASSEMBLER_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_BACKEND_H_
|
#ifndef XENIA_CPU_BACKEND_BACKEND_H_
|
||||||
#define XENIA_BACKEND_BACKEND_H_
|
#define XENIA_CPU_BACKEND_BACKEND_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class CodeCache;
|
||||||
|
|
||||||
class Backend {
|
class Backend {
|
||||||
public:
|
public:
|
||||||
Backend(Processor* processor);
|
explicit Backend(Processor* processor);
|
||||||
virtual ~Backend();
|
virtual ~Backend();
|
||||||
|
|
||||||
Processor* processor() const { return processor_; }
|
Processor* processor() const { return processor_; }
|
||||||
|
@ -61,4 +61,4 @@ class Backend {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_BACKEND_H_
|
#endif // XENIA_CPU_BACKEND_BACKEND_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_CODE_CACHE_H_
|
#ifndef XENIA_CPU_BACKEND_CODE_CACHE_H_
|
||||||
#define XENIA_BACKEND_CODE_CACHE_H_
|
#define XENIA_CPU_BACKEND_CODE_CACHE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -39,4 +39,4 @@ class CodeCache {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_CODE_CACHE_H_
|
#endif // XENIA_CPU_BACKEND_CODE_CACHE_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_MACHINE_INFO_H_
|
#ifndef XENIA_CPU_BACKEND_MACHINE_INFO_H_
|
||||||
#define XENIA_BACKEND_MACHINE_INFO_H_
|
#define XENIA_CPU_BACKEND_MACHINE_INFO_H_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -36,4 +36,4 @@ struct MachineInfo {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_MACHINE_INFO_H_
|
#endif // XENIA_CPU_BACKEND_MACHINE_INFO_H_
|
||||||
|
|
|
@ -26,9 +26,6 @@ namespace cpu {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
// TODO(benvanik): remove when enums redefined.
|
|
||||||
using namespace xe::cpu;
|
|
||||||
|
|
||||||
using xe::cpu::hir::HIRBuilder;
|
using xe::cpu::hir::HIRBuilder;
|
||||||
|
|
||||||
X64Assembler::X64Assembler(X64Backend* backend)
|
X64Assembler::X64Assembler(X64Backend* backend)
|
||||||
|
@ -78,7 +75,7 @@ bool X64Assembler::Assemble(GuestFunction* function, HIRBuilder* builder,
|
||||||
void* machine_code = nullptr;
|
void* machine_code = nullptr;
|
||||||
size_t code_size = 0;
|
size_t code_size = 0;
|
||||||
if (!emitter_->Emit(function, builder, debug_info_flags, debug_info.get(),
|
if (!emitter_->Emit(function, builder, debug_info_flags, debug_info.get(),
|
||||||
machine_code, code_size, function->source_map())) {
|
&machine_code, &code_size, &function->source_map())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_ASSEMBLER_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_ASSEMBLER_H_
|
||||||
#define XENIA_BACKEND_X64_X64_ASSEMBLER_H_
|
#define XENIA_CPU_BACKEND_X64_X64_ASSEMBLER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -28,7 +28,7 @@ class XbyakAllocator;
|
||||||
|
|
||||||
class X64Assembler : public Assembler {
|
class X64Assembler : public Assembler {
|
||||||
public:
|
public:
|
||||||
X64Assembler(X64Backend* backend);
|
explicit X64Assembler(X64Backend* backend);
|
||||||
~X64Assembler() override;
|
~X64Assembler() override;
|
||||||
|
|
||||||
bool Initialize() override;
|
bool Initialize() override;
|
||||||
|
@ -58,4 +58,4 @@ class X64Assembler : public Assembler {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_ASSEMBLER_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_ASSEMBLER_H_
|
||||||
|
|
|
@ -112,8 +112,6 @@ std::unique_ptr<GuestFunction> X64Backend::CreateGuestFunction(
|
||||||
return std::make_unique<X64Function>(module, address);
|
return std::make_unique<X64Function>(module, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Xbyak;
|
|
||||||
|
|
||||||
X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
|
X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||||
: X64Emitter(backend, allocator) {}
|
: X64Emitter(backend, allocator) {}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_BACKEND_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_BACKEND_H_
|
||||||
#define XENIA_BACKEND_X64_X64_BACKEND_H_
|
#define XENIA_CPU_BACKEND_X64_X64_BACKEND_H_
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
@ -33,9 +33,9 @@ typedef void (*ResolveFunctionThunk)();
|
||||||
|
|
||||||
class X64Backend : public Backend {
|
class X64Backend : public Backend {
|
||||||
public:
|
public:
|
||||||
const static uint32_t kForceReturnAddress = 0x9FFF0000u;
|
static const uint32_t kForceReturnAddress = 0x9FFF0000u;
|
||||||
|
|
||||||
X64Backend(Processor* processor);
|
explicit X64Backend(Processor* processor);
|
||||||
~X64Backend() override;
|
~X64Backend() override;
|
||||||
|
|
||||||
X64CodeCache* code_cache() const { return code_cache_.get(); }
|
X64CodeCache* code_cache() const { return code_cache_.get(); }
|
||||||
|
@ -74,4 +74,4 @@ class X64Backend : public Backend {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_BACKEND_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_BACKEND_H_
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_CODE_CACHE_H_
|
||||||
#define XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
#define XENIA_CPU_BACKEND_X64_X64_CODE_CACHE_H_
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/memory.h"
|
#include "xenia/base/memory.h"
|
||||||
|
@ -58,18 +59,18 @@ class X64CodeCache : public CodeCache {
|
||||||
protected:
|
protected:
|
||||||
// All executable code falls within 0x80000000 to 0x9FFFFFFF, so we can
|
// All executable code falls within 0x80000000 to 0x9FFFFFFF, so we can
|
||||||
// only map enough for lookups within that range.
|
// only map enough for lookups within that range.
|
||||||
const static uint64_t kIndirectionTableBase = 0x80000000;
|
static const uint64_t kIndirectionTableBase = 0x80000000;
|
||||||
const static uint64_t kIndirectionTableSize = 0x1FFFFFFF;
|
static const uint64_t kIndirectionTableSize = 0x1FFFFFFF;
|
||||||
// The code range is 512MB, but we know the total code games will have is
|
// The code range is 512MB, but we know the total code games will have is
|
||||||
// pretty small (dozens of mb at most) and our expansion is reasonablish
|
// pretty small (dozens of mb at most) and our expansion is reasonablish
|
||||||
// so 256MB should be more than enough.
|
// so 256MB should be more than enough.
|
||||||
const static uint64_t kGeneratedCodeBase = 0xA0000000;
|
static const uint64_t kGeneratedCodeBase = 0xA0000000;
|
||||||
const static uint64_t kGeneratedCodeSize = 0x0FFFFFFF;
|
static const uint64_t kGeneratedCodeSize = 0x0FFFFFFF;
|
||||||
|
|
||||||
// This is picked to be high enough to cover whatever we can reasonably
|
// This is picked to be high enough to cover whatever we can reasonably
|
||||||
// expect. If we hit issues with this it probably means some corner case
|
// expect. If we hit issues with this it probably means some corner case
|
||||||
// in analysis triggering.
|
// in analysis triggering.
|
||||||
const static size_t kMaximumFunctionCount = 30000;
|
static const size_t kMaximumFunctionCount = 30000;
|
||||||
|
|
||||||
struct UnwindReservation {
|
struct UnwindReservation {
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
|
@ -119,4 +120,4 @@ class X64CodeCache : public CodeCache {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_CODE_CACHE_H_
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace x64 {
|
||||||
|
|
||||||
// Size of unwind info per function.
|
// Size of unwind info per function.
|
||||||
// TODO(benvanik): move this to emitter.
|
// TODO(benvanik): move this to emitter.
|
||||||
const static uint32_t kUnwindInfoSize = 4 + (2 * 1 + 2 + 2);
|
static const uint32_t kUnwindInfoSize = 4 + (2 * 1 + 2 + 2);
|
||||||
|
|
||||||
class Win32X64CodeCache : public X64CodeCache {
|
class Win32X64CodeCache : public X64CodeCache {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -42,11 +42,6 @@ namespace cpu {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
// TODO(benvanik): remove when enums redefined.
|
|
||||||
using namespace xe::cpu::hir;
|
|
||||||
using namespace xe::cpu;
|
|
||||||
|
|
||||||
using namespace Xbyak;
|
|
||||||
using xe::cpu::hir::HIRBuilder;
|
using xe::cpu::hir::HIRBuilder;
|
||||||
using xe::cpu::hir::Instr;
|
using xe::cpu::hir::Instr;
|
||||||
|
|
||||||
|
@ -56,7 +51,8 @@ static const size_t kStashOffset = 32;
|
||||||
// static const size_t kStashOffsetHigh = 32 + 32;
|
// static const size_t kStashOffsetHigh = 32 + 32;
|
||||||
|
|
||||||
const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
|
const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
|
||||||
Operand::RBX, Operand::R12, Operand::R13, Operand::R14, Operand::R15,
|
Xbyak::Operand::RBX, Xbyak::Operand::R12, Xbyak::Operand::R13,
|
||||||
|
Xbyak::Operand::R14, Xbyak::Operand::R15,
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
|
const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
|
||||||
|
@ -64,7 +60,7 @@ const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
|
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||||
: CodeGenerator(kMaxCodeSize, AutoGrow, allocator),
|
: CodeGenerator(kMaxCodeSize, Xbyak::AutoGrow, allocator),
|
||||||
processor_(backend->processor()),
|
processor_(backend->processor()),
|
||||||
backend_(backend),
|
backend_(backend),
|
||||||
code_cache_(backend->code_cache()),
|
code_cache_(backend->code_cache()),
|
||||||
|
@ -90,8 +86,8 @@ X64Emitter::~X64Emitter() = default;
|
||||||
|
|
||||||
bool X64Emitter::Emit(GuestFunction* function, HIRBuilder* builder,
|
bool X64Emitter::Emit(GuestFunction* function, HIRBuilder* builder,
|
||||||
uint32_t debug_info_flags, DebugInfo* debug_info,
|
uint32_t debug_info_flags, DebugInfo* debug_info,
|
||||||
void*& out_code_address, size_t& out_code_size,
|
void** out_code_address, size_t* out_code_size,
|
||||||
std::vector<SourceMapEntry>& out_source_map) {
|
std::vector<SourceMapEntry>* out_source_map) {
|
||||||
SCOPE_profile_cpu_f("cpu");
|
SCOPE_profile_cpu_f("cpu");
|
||||||
|
|
||||||
// Reset.
|
// Reset.
|
||||||
|
@ -102,16 +98,16 @@ bool X64Emitter::Emit(GuestFunction* function, HIRBuilder* builder,
|
||||||
|
|
||||||
// Fill the generator with code.
|
// Fill the generator with code.
|
||||||
size_t stack_size = 0;
|
size_t stack_size = 0;
|
||||||
if (!Emit(builder, stack_size)) {
|
if (!Emit(builder, &stack_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the final code to the cache and relocate it.
|
// Copy the final code to the cache and relocate it.
|
||||||
out_code_size = getSize();
|
*out_code_size = getSize();
|
||||||
out_code_address = Emplace(stack_size, function);
|
*out_code_address = Emplace(stack_size, function);
|
||||||
|
|
||||||
// Stash source map.
|
// Stash source map.
|
||||||
source_map_arena_.CloneContents(&out_source_map);
|
source_map_arena_.CloneContents(out_source_map);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -129,14 +125,14 @@ void* X64Emitter::Emplace(size_t stack_size, GuestFunction* function) {
|
||||||
} else {
|
} else {
|
||||||
new_address = code_cache_->PlaceHostCode(0, top_, size_, stack_size);
|
new_address = code_cache_->PlaceHostCode(0, top_, size_, stack_size);
|
||||||
}
|
}
|
||||||
top_ = (uint8_t*)new_address;
|
top_ = reinterpret_cast<uint8_t*>(new_address);
|
||||||
ready();
|
ready();
|
||||||
top_ = old_address;
|
top_ = old_address;
|
||||||
reset();
|
reset();
|
||||||
return new_address;
|
return new_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
bool X64Emitter::Emit(HIRBuilder* builder, size_t* out_stack_size) {
|
||||||
Xbyak::Label epilog_label;
|
Xbyak::Label epilog_label;
|
||||||
epilog_label_ = &epilog_label;
|
epilog_label_ = &epilog_label;
|
||||||
|
|
||||||
|
@ -169,7 +165,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||||
// Adding or changing anything here must be matched!
|
// Adding or changing anything here must be matched!
|
||||||
const size_t stack_size = StackLayout::GUEST_STACK_SIZE + stack_offset;
|
const size_t stack_size = StackLayout::GUEST_STACK_SIZE + stack_offset;
|
||||||
assert_true((stack_size + 8) % 16 == 0);
|
assert_true((stack_size + 8) % 16 == 0);
|
||||||
out_stack_size = stack_size;
|
*out_stack_size = stack_size;
|
||||||
stack_size_ = stack_size;
|
stack_size_ = stack_size;
|
||||||
sub(rsp, (uint32_t)stack_size);
|
sub(rsp, (uint32_t)stack_size);
|
||||||
mov(qword[rsp + StackLayout::GUEST_RCX_HOME], rcx);
|
mov(qword[rsp + StackLayout::GUEST_RCX_HOME], rcx);
|
||||||
|
@ -190,10 +186,10 @@ bool X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||||
static_assert(debug::FunctionTraceData::kFunctionCallerHistoryCount == 4,
|
static_assert(debug::FunctionTraceData::kFunctionCallerHistoryCount == 4,
|
||||||
"bitmask depends on count");
|
"bitmask depends on count");
|
||||||
mov(rax, qword[low_address(&trace_header->function_call_count)]);
|
mov(rax, qword[low_address(&trace_header->function_call_count)]);
|
||||||
and_(rax, B00000011);
|
and_(rax, 0b00000011);
|
||||||
|
|
||||||
// Record call history value into slot (guest addr in RDX).
|
// Record call history value into slot (guest addr in RDX).
|
||||||
mov(dword[RegExp(uint32_t(uint64_t(
|
mov(dword[Xbyak::RegExp(uint32_t(uint64_t(
|
||||||
low_address(&trace_header->function_caller_history)))) +
|
low_address(&trace_header->function_caller_history)))) +
|
||||||
rax * 4],
|
rax * 4],
|
||||||
edx);
|
edx);
|
||||||
|
@ -221,7 +217,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||||
const Instr* instr = block->instr_head;
|
const Instr* instr = block->instr_head;
|
||||||
while (instr) {
|
while (instr) {
|
||||||
const Instr* new_tail = instr;
|
const Instr* new_tail = instr;
|
||||||
if (!SelectSequence(*this, instr, &new_tail)) {
|
if (!SelectSequence(this, instr, &new_tail)) {
|
||||||
// No sequence found!
|
// No sequence found!
|
||||||
assert_always();
|
assert_always();
|
||||||
XELOGE("Unable to process HIR opcode %s", instr->opcode->name);
|
XELOGE("Unable to process HIR opcode %s", instr->opcode->name);
|
||||||
|
@ -368,7 +364,7 @@ void X64Emitter::Call(const hir::Instr* instr, GuestFunction* function) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually jump/call to rax.
|
// Actually jump/call to rax.
|
||||||
if (instr->flags & CALL_TAIL) {
|
if (instr->flags & hir::CALL_TAIL) {
|
||||||
// Since we skip the prolog we need to mark the return here.
|
// Since we skip the prolog we need to mark the return here.
|
||||||
EmitTraceUserCallReturn();
|
EmitTraceUserCallReturn();
|
||||||
|
|
||||||
|
@ -385,9 +381,10 @@ void X64Emitter::Call(const hir::Instr* instr, GuestFunction* function) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::CallIndirect(const hir::Instr* instr, const Reg64& reg) {
|
void X64Emitter::CallIndirect(const hir::Instr* instr,
|
||||||
|
const Xbyak::Reg64& reg) {
|
||||||
// Check if return.
|
// Check if return.
|
||||||
if (instr->flags & CALL_POSSIBLE_RETURN) {
|
if (instr->flags & hir::CALL_POSSIBLE_RETURN) {
|
||||||
cmp(reg.cvt32(), dword[rsp + StackLayout::GUEST_RET_ADDR]);
|
cmp(reg.cvt32(), dword[rsp + StackLayout::GUEST_RET_ADDR]);
|
||||||
je(epilog_label(), CodeGenerator::T_NEAR);
|
je(epilog_label(), CodeGenerator::T_NEAR);
|
||||||
}
|
}
|
||||||
|
@ -401,7 +398,7 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, const Reg64& reg) {
|
||||||
mov(eax, dword[ebx]);
|
mov(eax, dword[ebx]);
|
||||||
|
|
||||||
// Actually jump/call to rax.
|
// Actually jump/call to rax.
|
||||||
if (instr->flags & CALL_TAIL) {
|
if (instr->flags & hir::CALL_TAIL) {
|
||||||
// Since we skip the prolog we need to mark the return here.
|
// Since we skip the prolog we need to mark the return here.
|
||||||
EmitTraceUserCallReturn();
|
EmitTraceUserCallReturn();
|
||||||
|
|
||||||
|
@ -550,7 +547,7 @@ bool X64Emitter::ConstantFitsIn32Reg(uint64_t v) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::MovMem64(const RegExp& addr, uint64_t v) {
|
void X64Emitter::MovMem64(const Xbyak::RegExp& addr, uint64_t v) {
|
||||||
if ((v & ~0x7FFFFFFF) == 0) {
|
if ((v & ~0x7FFFFFFF) == 0) {
|
||||||
// Fits under 31 bits, so just load using normal mov.
|
// Fits under 31 bits, so just load using normal mov.
|
||||||
mov(qword[addr], v);
|
mov(qword[addr], v);
|
||||||
|
@ -651,7 +648,7 @@ uint32_t X64Emitter::PlaceData(Memory* memory) {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
Xbyak::Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||||
// Load through fixed constant table setup by PlaceData.
|
// Load through fixed constant table setup by PlaceData.
|
||||||
return ptr[rdx + backend_->emitter_data() + sizeof(vec128_t) * id];
|
return ptr[rdx + backend_->emitter_data() + sizeof(vec128_t) * id];
|
||||||
}
|
}
|
||||||
|
@ -712,7 +709,7 @@ void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, double v) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Address X64Emitter::StashXmm(int index, const Xmm& r) {
|
Xbyak::Address X64Emitter::StashXmm(int index, const Xbyak::Xmm& r) {
|
||||||
auto addr = ptr[rsp + kStashOffset + (index * 16)];
|
auto addr = ptr[rsp + kStashOffset + (index * 16)];
|
||||||
vmovups(addr, r);
|
vmovups(addr, r);
|
||||||
return addr;
|
return addr;
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_EMITTER_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_EMITTER_H_
|
||||||
#define XENIA_BACKEND_X64_X64_EMITTER_H_
|
#define XENIA_CPU_BACKEND_X64_X64_EMITTER_H_
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -116,8 +116,8 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||||
|
|
||||||
bool Emit(GuestFunction* function, hir::HIRBuilder* builder,
|
bool Emit(GuestFunction* function, hir::HIRBuilder* builder,
|
||||||
uint32_t debug_info_flags, DebugInfo* debug_info,
|
uint32_t debug_info_flags, DebugInfo* debug_info,
|
||||||
void*& out_code_address, size_t& out_code_size,
|
void** out_code_address, size_t* out_code_size,
|
||||||
std::vector<SourceMapEntry>& out_source_map);
|
std::vector<SourceMapEntry>* out_source_map);
|
||||||
|
|
||||||
static uint32_t PlaceData(Memory* memory);
|
static uint32_t PlaceData(Memory* memory);
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void* Emplace(size_t stack_size, GuestFunction* function = nullptr);
|
void* Emplace(size_t stack_size, GuestFunction* function = nullptr);
|
||||||
bool Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
bool Emit(hir::HIRBuilder* builder, size_t* out_stack_size);
|
||||||
void EmitGetCurrentThreadId();
|
void EmitGetCurrentThreadId();
|
||||||
void EmitTraceUserCallReturn();
|
void EmitTraceUserCallReturn();
|
||||||
|
|
||||||
|
@ -228,4 +228,4 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_EMITTER_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_EMITTER_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_FUNCTION_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_FUNCTION_H_
|
||||||
#define XENIA_BACKEND_X64_X64_FUNCTION_H_
|
#define XENIA_CPU_BACKEND_X64_X64_FUNCTION_H_
|
||||||
|
|
||||||
#include "xenia/cpu/function.h"
|
#include "xenia/cpu/function.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
@ -41,4 +41,4 @@ class X64Function : public GuestFunction {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_FUNCTION_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_FUNCTION_H_
|
||||||
|
|
|
@ -1477,16 +1477,16 @@ struct ROUND_F32 : Sequence<ROUND_F32, I<OPCODE_ROUND, F32Op, F32Op>> {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
switch (i.instr->flags) {
|
switch (i.instr->flags) {
|
||||||
case ROUND_TO_ZERO:
|
case ROUND_TO_ZERO:
|
||||||
e.vroundss(i.dest, i.src1, B00000011);
|
e.vroundss(i.dest, i.src1, 0b00000011);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_NEAREST:
|
case ROUND_TO_NEAREST:
|
||||||
e.vroundss(i.dest, i.src1, B00000000);
|
e.vroundss(i.dest, i.src1, 0b00000000);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_MINUS_INFINITY:
|
case ROUND_TO_MINUS_INFINITY:
|
||||||
e.vroundss(i.dest, i.src1, B00000001);
|
e.vroundss(i.dest, i.src1, 0b00000001);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_POSITIVE_INFINITY:
|
case ROUND_TO_POSITIVE_INFINITY:
|
||||||
e.vroundss(i.dest, i.src1, B00000010);
|
e.vroundss(i.dest, i.src1, 0b00000010);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1495,16 +1495,16 @@ struct ROUND_F64 : Sequence<ROUND_F64, I<OPCODE_ROUND, F64Op, F64Op>> {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
switch (i.instr->flags) {
|
switch (i.instr->flags) {
|
||||||
case ROUND_TO_ZERO:
|
case ROUND_TO_ZERO:
|
||||||
e.vroundsd(i.dest, i.src1, B00000011);
|
e.vroundsd(i.dest, i.src1, 0b00000011);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_NEAREST:
|
case ROUND_TO_NEAREST:
|
||||||
e.vroundsd(i.dest, i.src1, B00000000);
|
e.vroundsd(i.dest, i.src1, 0b00000000);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_MINUS_INFINITY:
|
case ROUND_TO_MINUS_INFINITY:
|
||||||
e.vroundsd(i.dest, i.src1, B00000001);
|
e.vroundsd(i.dest, i.src1, 0b00000001);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_POSITIVE_INFINITY:
|
case ROUND_TO_POSITIVE_INFINITY:
|
||||||
e.vroundsd(i.dest, i.src1, B00000010);
|
e.vroundsd(i.dest, i.src1, 0b00000010);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1513,16 +1513,16 @@ struct ROUND_V128 : Sequence<ROUND_V128, I<OPCODE_ROUND, V128Op, V128Op>> {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
switch (i.instr->flags) {
|
switch (i.instr->flags) {
|
||||||
case ROUND_TO_ZERO:
|
case ROUND_TO_ZERO:
|
||||||
e.vroundps(i.dest, i.src1, B00000011);
|
e.vroundps(i.dest, i.src1, 0b00000011);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_NEAREST:
|
case ROUND_TO_NEAREST:
|
||||||
e.vroundps(i.dest, i.src1, B00000000);
|
e.vroundps(i.dest, i.src1, 0b00000000);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_MINUS_INFINITY:
|
case ROUND_TO_MINUS_INFINITY:
|
||||||
e.vroundps(i.dest, i.src1, B00000001);
|
e.vroundps(i.dest, i.src1, 0b00000001);
|
||||||
break;
|
break;
|
||||||
case ROUND_TO_POSITIVE_INFINITY:
|
case ROUND_TO_POSITIVE_INFINITY:
|
||||||
e.vroundps(i.dest, i.src1, B00000010);
|
e.vroundps(i.dest, i.src1, 0b00000010);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4791,7 +4791,7 @@ struct DOT_PRODUCT_3_V128
|
||||||
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
|
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
|
||||||
// TODO(benvanik): apparently this is very slow
|
// TODO(benvanik): apparently this is very slow
|
||||||
// - find alternative?
|
// - find alternative?
|
||||||
e.vdpps(dest, src1, src2, B01110001);
|
e.vdpps(dest, src1, src2, 0b01110001);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4809,7 +4809,7 @@ struct DOT_PRODUCT_4_V128
|
||||||
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
|
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
|
||||||
// TODO(benvanik): apparently this is very slow
|
// TODO(benvanik): apparently this is very slow
|
||||||
// - find alternative?
|
// - find alternative?
|
||||||
e.vdpps(dest, src1, src2, B11110001);
|
e.vdpps(dest, src1, src2, 0b11110001);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6454,7 +6454,7 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
|
||||||
|
|
||||||
if (e.IsFeatureEnabled(kX64EmitF16C)) {
|
if (e.IsFeatureEnabled(kX64EmitF16C)) {
|
||||||
// 0|0|0|0|W|Z|Y|X
|
// 0|0|0|0|W|Z|Y|X
|
||||||
e.vcvtps2ph(i.dest, i.dest, B00000011);
|
e.vcvtps2ph(i.dest, i.dest, 0b00000011);
|
||||||
// Shuffle to X|Y|0|0|0|0|0|0
|
// Shuffle to X|Y|0|0|0|0|0|0
|
||||||
e.vpshufb(i.dest, i.dest, e.GetXmmConstPtr(XMMPackFLOAT16_2));
|
e.vpshufb(i.dest, i.dest, e.GetXmmConstPtr(XMMPackFLOAT16_2));
|
||||||
} else {
|
} else {
|
||||||
|
@ -6481,7 +6481,7 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
|
||||||
|
|
||||||
if (e.IsFeatureEnabled(kX64EmitF16C)) {
|
if (e.IsFeatureEnabled(kX64EmitF16C)) {
|
||||||
// 0|0|0|0|W|Z|Y|X
|
// 0|0|0|0|W|Z|Y|X
|
||||||
e.vcvtps2ph(i.dest, i.src1, B00000011);
|
e.vcvtps2ph(i.dest, i.src1, 0b00000011);
|
||||||
// Shuffle to X|Y|Z|W|0|0|0|0
|
// Shuffle to X|Y|Z|W|0|0|0|0
|
||||||
e.vpshufb(i.dest, i.dest, e.GetXmmConstPtr(XMMPackFLOAT16_4));
|
e.vpshufb(i.dest, i.dest, e.GetXmmConstPtr(XMMPackFLOAT16_4));
|
||||||
} else {
|
} else {
|
||||||
|
@ -6639,8 +6639,8 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
|
||||||
src2 = e.xmm0;
|
src2 = e.xmm0;
|
||||||
}
|
}
|
||||||
e.vpackusdw(i.dest, i.src1, src2);
|
e.vpackusdw(i.dest, i.src1, src2);
|
||||||
e.vpshuflw(i.dest, i.dest, B10110001);
|
e.vpshuflw(i.dest, i.dest, 0b10110001);
|
||||||
e.vpshufhw(i.dest, i.dest, B10110001);
|
e.vpshufhw(i.dest, i.dest, 0b10110001);
|
||||||
} else {
|
} else {
|
||||||
// unsigned -> unsigned
|
// unsigned -> unsigned
|
||||||
assert_always();
|
assert_always();
|
||||||
|
@ -7125,11 +7125,11 @@ void RegisterSequences() {
|
||||||
Register_OPCODE_ATOMIC_EXCHANGE();
|
Register_OPCODE_ATOMIC_EXCHANGE();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SelectSequence(X64Emitter& e, const Instr* i, const Instr** new_tail) {
|
bool SelectSequence(X64Emitter* e, const Instr* i, const Instr** new_tail) {
|
||||||
const InstrKey key(i);
|
const InstrKey key(i);
|
||||||
auto it = sequence_table.find(key);
|
auto it = sequence_table.find(key);
|
||||||
if (it != sequence_table.end()) {
|
if (it != sequence_table.end()) {
|
||||||
if (it->second(e, i)) {
|
if (it->second(*e, i)) {
|
||||||
*new_tail = i->next;
|
*new_tail = i->next;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,10 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_SEQUENCES_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_SEQUENCES_H_
|
||||||
#define XENIA_BACKEND_X64_X64_SEQUENCES_H_
|
#define XENIA_CPU_BACKEND_X64_X64_SEQUENCES_H_
|
||||||
|
|
||||||
namespace xe {
|
#include "xenia/cpu/hir/instr.h"
|
||||||
namespace cpu {
|
|
||||||
namespace hir {
|
|
||||||
class Instr;
|
|
||||||
} // namespace hir
|
|
||||||
} // namespace cpu
|
|
||||||
} // namespace xe
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
@ -26,7 +20,7 @@ namespace x64 {
|
||||||
class X64Emitter;
|
class X64Emitter;
|
||||||
|
|
||||||
void RegisterSequences();
|
void RegisterSequences();
|
||||||
bool SelectSequence(X64Emitter& e, const hir::Instr* i,
|
bool SelectSequence(X64Emitter* e, const hir::Instr* i,
|
||||||
const hir::Instr** new_tail);
|
const hir::Instr** new_tail);
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
|
@ -34,4 +28,4 @@ bool SelectSequence(X64Emitter& e, const hir::Instr* i,
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_SEQUENCES_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_SEQUENCES_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||||
#define XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
#define XENIA_CPU_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||||
|
|
||||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||||
|
@ -115,12 +115,12 @@ namespace x64 {
|
||||||
|
|
||||||
class StackLayout {
|
class StackLayout {
|
||||||
public:
|
public:
|
||||||
const static size_t THUNK_STACK_SIZE = 120;
|
static const size_t THUNK_STACK_SIZE = 120;
|
||||||
|
|
||||||
const static size_t GUEST_STACK_SIZE = 104;
|
static const size_t GUEST_STACK_SIZE = 104;
|
||||||
const static size_t GUEST_RCX_HOME = 80;
|
static const size_t GUEST_RCX_HOME = 80;
|
||||||
const static size_t GUEST_RET_ADDR = 88;
|
static const size_t GUEST_RET_ADDR = 88;
|
||||||
const static size_t GUEST_CALL_RET_ADDR = 96;
|
static const size_t GUEST_CALL_RET_ADDR = 96;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
|
@ -128,4 +128,4 @@ class StackLayout {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||||
|
|
|
@ -58,41 +58,41 @@ uint32_t GetTracingMode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceString(void* raw_context, const char* str) {
|
void TraceString(void* raw_context, const char* str) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
IPRINT("XE[t] :%d: %s\n", thread_state->thread_id(), str);
|
IPRINT("XE[t] :%d: %s\n", thread_state->thread_id(), str);
|
||||||
IFLUSH();
|
IFLUSH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceContextLoadI8(void* raw_context, uint64_t offset, uint8_t value) {
|
void TraceContextLoadI8(void* raw_context, uint64_t offset, uint8_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%d (%X) = ctx i8 +%llu\n", (int8_t)value, value, offset);
|
DPRINT("%d (%X) = ctx i8 +%llu\n", (int8_t)value, value, offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadI16(void* raw_context, uint64_t offset, uint16_t value) {
|
void TraceContextLoadI16(void* raw_context, uint64_t offset, uint16_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%d (%X) = ctx i16 +%llu\n", (int16_t)value, value, offset);
|
DPRINT("%d (%X) = ctx i16 +%llu\n", (int16_t)value, value, offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadI32(void* raw_context, uint64_t offset, uint32_t value) {
|
void TraceContextLoadI32(void* raw_context, uint64_t offset, uint32_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%d (%X) = ctx i32 +%llu\n", (int32_t)value, value, offset);
|
DPRINT("%d (%X) = ctx i32 +%llu\n", (int32_t)value, value, offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadI64(void* raw_context, uint64_t offset, uint64_t value) {
|
void TraceContextLoadI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%lld (%llX) = ctx i64 +%llu\n", (int64_t)value, value, offset);
|
DPRINT("%lld (%llX) = ctx i64 +%llu\n", (int64_t)value, value, offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadF32(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextLoadF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%e (%X) = ctx f32 +%llu\n", xe::m128_f32<0>(value),
|
DPRINT("%e (%X) = ctx f32 +%llu\n", xe::m128_f32<0>(value),
|
||||||
xe::m128_i32<0>(value), offset);
|
xe::m128_i32<0>(value), offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadF64(void* raw_context, uint64_t offset,
|
void TraceContextLoadF64(void* raw_context, uint64_t offset,
|
||||||
const double* value) {
|
const double* value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
auto v = _mm_loadu_pd(value);
|
auto v = _mm_loadu_pd(value);
|
||||||
DPRINT("%le (%llX) = ctx f64 +%llu\n", xe::m128_f64<0>(v), xe::m128_i64<0>(v),
|
DPRINT("%le (%llX) = ctx f64 +%llu\n", xe::m128_f64<0>(v), xe::m128_i64<0>(v),
|
||||||
offset);
|
offset);
|
||||||
}
|
}
|
||||||
void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%llu\n",
|
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%llu\n",
|
||||||
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
||||||
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
||||||
|
@ -100,35 +100,35 @@ void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceContextStoreI8(void* raw_context, uint64_t offset, uint8_t value) {
|
void TraceContextStoreI8(void* raw_context, uint64_t offset, uint8_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("ctx i8 +%llu = %d (%X)\n", offset, (int8_t)value, value);
|
DPRINT("ctx i8 +%llu = %d (%X)\n", offset, (int8_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceContextStoreI16(void* raw_context, uint64_t offset, uint16_t value) {
|
void TraceContextStoreI16(void* raw_context, uint64_t offset, uint16_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("ctx i16 +%llu = %d (%X)\n", offset, (int16_t)value, value);
|
DPRINT("ctx i16 +%llu = %d (%X)\n", offset, (int16_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceContextStoreI32(void* raw_context, uint64_t offset, uint32_t value) {
|
void TraceContextStoreI32(void* raw_context, uint64_t offset, uint32_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("ctx i32 +%llu = %d (%X)\n", offset, (int32_t)value, value);
|
DPRINT("ctx i32 +%llu = %d (%X)\n", offset, (int32_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceContextStoreI64(void* raw_context, uint64_t offset, uint64_t value) {
|
void TraceContextStoreI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("ctx i64 +%llu = %lld (%llX)\n", offset, (int64_t)value, value);
|
DPRINT("ctx i64 +%llu = %lld (%llX)\n", offset, (int64_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceContextStoreF32(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextStoreF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("ctx f32 +%llu = %e (%X)\n", offset, xe::m128_f32<0>(value),
|
DPRINT("ctx f32 +%llu = %e (%X)\n", offset, xe::m128_f32<0>(value),
|
||||||
xe::m128_i32<0>(value));
|
xe::m128_i32<0>(value));
|
||||||
}
|
}
|
||||||
void TraceContextStoreF64(void* raw_context, uint64_t offset,
|
void TraceContextStoreF64(void* raw_context, uint64_t offset,
|
||||||
const double* value) {
|
const double* value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
auto v = _mm_loadu_pd(value);
|
auto v = _mm_loadu_pd(value);
|
||||||
DPRINT("ctx f64 +%llu = %le (%llX)\n", offset, xe::m128_f64<0>(v),
|
DPRINT("ctx f64 +%llu = %le (%llX)\n", offset, xe::m128_f64<0>(v),
|
||||||
xe::m128_i64<0>(v));
|
xe::m128_i64<0>(v));
|
||||||
}
|
}
|
||||||
void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("ctx v128 +%llu = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", offset,
|
DPRINT("ctx v128 +%llu = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", offset,
|
||||||
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
||||||
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
||||||
|
@ -136,33 +136,33 @@ void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceMemoryLoadI8(void* raw_context, uint32_t address, uint8_t value) {
|
void TraceMemoryLoadI8(void* raw_context, uint32_t address, uint8_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%d (%X) = load.i8 %.8X\n", (int8_t)value, value, address);
|
DPRINT("%d (%X) = load.i8 %.8X\n", (int8_t)value, value, address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadI16(void* raw_context, uint32_t address, uint16_t value) {
|
void TraceMemoryLoadI16(void* raw_context, uint32_t address, uint16_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%d (%X) = load.i16 %.8X\n", (int16_t)value, value, address);
|
DPRINT("%d (%X) = load.i16 %.8X\n", (int16_t)value, value, address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadI32(void* raw_context, uint32_t address, uint32_t value) {
|
void TraceMemoryLoadI32(void* raw_context, uint32_t address, uint32_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%d (%X) = load.i32 %.8X\n", (int32_t)value, value, address);
|
DPRINT("%d (%X) = load.i32 %.8X\n", (int32_t)value, value, address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadI64(void* raw_context, uint32_t address, uint64_t value) {
|
void TraceMemoryLoadI64(void* raw_context, uint32_t address, uint64_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%lld (%llX) = load.i64 %.8X\n", (int64_t)value, value, address);
|
DPRINT("%lld (%llX) = load.i64 %.8X\n", (int64_t)value, value, address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadF32(void* raw_context, uint32_t address, __m128 value) {
|
void TraceMemoryLoadF32(void* raw_context, uint32_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%e (%X) = load.f32 %.8X\n", xe::m128_f32<0>(value),
|
DPRINT("%e (%X) = load.f32 %.8X\n", xe::m128_f32<0>(value),
|
||||||
xe::m128_i32<0>(value), address);
|
xe::m128_i32<0>(value), address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadF64(void* raw_context, uint32_t address, __m128 value) {
|
void TraceMemoryLoadF64(void* raw_context, uint32_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("%le (%llX) = load.f64 %.8X\n", xe::m128_f64<0>(value),
|
DPRINT("%le (%llX) = load.f64 %.8X\n", xe::m128_f64<0>(value),
|
||||||
xe::m128_i64<0>(value), address);
|
xe::m128_i64<0>(value), address);
|
||||||
}
|
}
|
||||||
void TraceMemoryLoadV128(void* raw_context, uint32_t address, __m128 value) {
|
void TraceMemoryLoadV128(void* raw_context, uint32_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n",
|
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n",
|
||||||
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
xe::m128_f32<0>(value), xe::m128_f32<1>(value), xe::m128_f32<2>(value),
|
||||||
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
xe::m128_f32<3>(value), xe::m128_i32<0>(value), xe::m128_i32<1>(value),
|
||||||
|
@ -170,33 +170,33 @@ void TraceMemoryLoadV128(void* raw_context, uint32_t address, __m128 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceMemoryStoreI8(void* raw_context, uint32_t address, uint8_t value) {
|
void TraceMemoryStoreI8(void* raw_context, uint32_t address, uint8_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.i8 %.8X = %d (%X)\n", address, (int8_t)value, value);
|
DPRINT("store.i8 %.8X = %d (%X)\n", address, (int8_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreI16(void* raw_context, uint32_t address, uint16_t value) {
|
void TraceMemoryStoreI16(void* raw_context, uint32_t address, uint16_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.i16 %.8X = %d (%X)\n", address, (int16_t)value, value);
|
DPRINT("store.i16 %.8X = %d (%X)\n", address, (int16_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreI32(void* raw_context, uint32_t address, uint32_t value) {
|
void TraceMemoryStoreI32(void* raw_context, uint32_t address, uint32_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.i32 %.8X = %d (%X)\n", address, (int32_t)value, value);
|
DPRINT("store.i32 %.8X = %d (%X)\n", address, (int32_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreI64(void* raw_context, uint32_t address, uint64_t value) {
|
void TraceMemoryStoreI64(void* raw_context, uint32_t address, uint64_t value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.i64 %.8X = %lld (%llX)\n", address, (int64_t)value, value);
|
DPRINT("store.i64 %.8X = %lld (%llX)\n", address, (int64_t)value, value);
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreF32(void* raw_context, uint32_t address, __m128 value) {
|
void TraceMemoryStoreF32(void* raw_context, uint32_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.f32 %.8X = %e (%X)\n", address, xe::m128_f32<0>(value),
|
DPRINT("store.f32 %.8X = %e (%X)\n", address, xe::m128_f32<0>(value),
|
||||||
xe::m128_i32<0>(value));
|
xe::m128_i32<0>(value));
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreF64(void* raw_context, uint32_t address, __m128 value) {
|
void TraceMemoryStoreF64(void* raw_context, uint32_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.f64 %.8X = %le (%llX)\n", address, xe::m128_f64<0>(value),
|
DPRINT("store.f64 %.8X = %le (%llX)\n", address, xe::m128_f64<0>(value),
|
||||||
xe::m128_i64<0>(value));
|
xe::m128_i64<0>(value));
|
||||||
}
|
}
|
||||||
void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value) {
|
void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n",
|
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n",
|
||||||
address, xe::m128_f32<0>(value), xe::m128_f32<1>(value),
|
address, xe::m128_f32<0>(value), xe::m128_f32<1>(value),
|
||||||
xe::m128_f32<2>(value), xe::m128_f32<3>(value), xe::m128_i32<0>(value),
|
xe::m128_f32<2>(value), xe::m128_f32<3>(value), xe::m128_i32<0>(value),
|
||||||
|
@ -206,7 +206,7 @@ void TraceMemoryStoreV128(void* raw_context, uint32_t address, __m128 value) {
|
||||||
|
|
||||||
void TraceMemset(void* raw_context, uint32_t address, uint8_t value,
|
void TraceMemset(void* raw_context, uint32_t address, uint8_t value,
|
||||||
uint32_t length) {
|
uint32_t length) {
|
||||||
auto thread_state = *((ThreadState**)raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
DPRINT("memset %.8X-%.8X (%d) = %.2X", address, address + length, length,
|
DPRINT("memset %.8X-%.8X (%d) = %.2X", address, address + length, length,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_TRACERS_H_
|
#ifndef XENIA_CPU_BACKEND_X64_X64_TRACERS_H_
|
||||||
#define XENIA_BACKEND_X64_X64_TRACERS_H_
|
#define XENIA_CPU_BACKEND_X64_X64_TRACERS_H_
|
||||||
|
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -72,4 +72,4 @@ void TraceMemset(void* raw_context, uint32_t address, uint8_t value,
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_TRACERS_H_
|
#endif // XENIA_CPU_BACKEND_X64_X64_TRACERS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_COMPILER_H_
|
#ifndef XENIA_CPU_COMPILER_COMPILER_H_
|
||||||
#define XENIA_COMPILER_COMPILER_H_
|
#define XENIA_CPU_COMPILER_COMPILER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -30,7 +30,7 @@ class CompilerPass;
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
Compiler(Processor* processor);
|
explicit Compiler(Processor* processor);
|
||||||
~Compiler();
|
~Compiler();
|
||||||
|
|
||||||
Processor* processor() const { return processor_; }
|
Processor* processor() const { return processor_; }
|
||||||
|
@ -53,4 +53,4 @@ class Compiler {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_COMPILER_H_
|
#endif // XENIA_CPU_COMPILER_COMPILER_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_COMPILER_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_COMPILER_PASS_H_
|
||||||
#define XENIA_COMPILER_COMPILER_PASS_H_
|
#define XENIA_CPU_COMPILER_COMPILER_PASS_H_
|
||||||
|
|
||||||
#include "xenia/base/arena.h"
|
#include "xenia/base/arena.h"
|
||||||
#include "xenia/cpu/hir/hir_builder.h"
|
#include "xenia/cpu/hir/hir_builder.h"
|
||||||
|
@ -46,4 +46,4 @@ class CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_COMPILER_PASS_H_
|
#endif // XENIA_CPU_COMPILER_COMPILER_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_COMPILER_PASSES_H_
|
#ifndef XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
||||||
#define XENIA_COMPILER_COMPILER_PASSES_H_
|
#define XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/context_promotion_pass.h"
|
#include "xenia/cpu/compiler/passes/context_promotion_pass.h"
|
||||||
|
@ -16,7 +16,6 @@
|
||||||
#include "xenia/cpu/compiler/passes/control_flow_simplification_pass.h"
|
#include "xenia/cpu/compiler/passes/control_flow_simplification_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/data_flow_analysis_pass.h"
|
#include "xenia/cpu/compiler/passes/data_flow_analysis_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/dead_code_elimination_pass.h"
|
#include "xenia/cpu/compiler/passes/dead_code_elimination_pass.h"
|
||||||
//#include "xenia/cpu/compiler/passes/dead_store_elimination_pass.h"
|
|
||||||
#include "xenia/cpu/compiler/passes/finalization_pass.h"
|
#include "xenia/cpu/compiler/passes/finalization_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/memory_sequence_combination_pass.h"
|
#include "xenia/cpu/compiler/passes/memory_sequence_combination_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/register_allocation_pass.h"
|
#include "xenia/cpu/compiler/passes/register_allocation_pass.h"
|
||||||
|
@ -24,4 +23,4 @@
|
||||||
#include "xenia/cpu/compiler/passes/validation_pass.h"
|
#include "xenia/cpu/compiler/passes/validation_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/value_reduction_pass.h"
|
#include "xenia/cpu/compiler/passes/value_reduction_pass.h"
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_COMPILER_PASSES_H_
|
#endif // XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@ class ConstantPropagationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/base/platform.h"
|
#include "xenia/base/platform.h"
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
@ -52,4 +52,4 @@ class ContextPromotionPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_CONTEXT_PROMOTION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@ class ControlFlowAnalysisPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@ class ControlFlowSimplificationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -34,4 +34,4 @@ class DataFlowAnalysisPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_DATA_FLOW_ANALYSIS_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -35,4 +35,4 @@ class DeadCodeEliminationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_DEAD_CODE_ELIMINATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_FINALIZATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_FINALIZATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@ class FinalizationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_FINALIZATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_FINALIZATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_MEMORY_SEQUENCE_COMBINATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_MEMORY_SEQUENCE_COMBINATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_MEMORY_SEQUENCE_COMBINATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_MEMORY_SEQUENCE_COMBINATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -35,4 +35,4 @@ class MemorySequenceCombinationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_MEMORY_SEQUENCE_COMBINATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_MEMORY_SEQUENCE_COMBINATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
@ -84,4 +84,4 @@ class RegisterAllocationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -38,4 +38,4 @@ class SimplificationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_VALIDATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_VALIDATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -34,4 +34,4 @@ class ValidationPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_VALIDATION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_VALIDATION_PASS_H_
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||||
#define XENIA_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
|
||||||
|
@ -33,4 +33,4 @@ class ValueReductionPass : public CompilerPass {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
#endif // XENIA_CPU_COMPILER_PASSES_VALUE_REDUCTION_PASS_H_
|
||||||
|
|
|
@ -437,7 +437,7 @@ bool RunTests(const std::wstring& test_name) {
|
||||||
return failed_count ? false : true;
|
return failed_count ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(std::vector<std::wstring>& args) {
|
int main(const std::vector<std::wstring>& args) {
|
||||||
// Grab test name, if present.
|
// Grab test name, if present.
|
||||||
std::wstring test_name;
|
std::wstring test_name;
|
||||||
if (args.size() >= 2) {
|
if (args.size() >= 2) {
|
||||||
|
|
|
@ -1933,7 +1933,7 @@ Value* HIRBuilder::CountLeadingZeros(Value* value) {
|
||||||
ASSERT_INTEGER_TYPE(value);
|
ASSERT_INTEGER_TYPE(value);
|
||||||
|
|
||||||
if (value->IsConstantZero()) {
|
if (value->IsConstantZero()) {
|
||||||
const static uint8_t zeros[] = {
|
static const uint8_t zeros[] = {
|
||||||
8, 16, 32, 64,
|
8, 16, 32, 64,
|
||||||
};
|
};
|
||||||
assert_true(value->type <= INT64_TYPE);
|
assert_true(value->type <= INT64_TYPE);
|
||||||
|
|
|
@ -223,7 +223,7 @@ struct DecodedMov {
|
||||||
int32_t constant;
|
int32_t constant;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
bool TryDecodeMov(const uint8_t* p, DecodedMov* mov) {
|
||||||
uint8_t i = 0; // Current byte decode index.
|
uint8_t i = 0; // Current byte decode index.
|
||||||
uint8_t rex = 0;
|
uint8_t rex = 0;
|
||||||
if ((p[i] & 0xF0) == 0x40) {
|
if ((p[i] & 0xF0) == 0x40) {
|
||||||
|
@ -236,8 +236,8 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
// 44 0f 38 f1 a4 02 00 movbe DWORD PTR [rdx+rax*1+0x0],r12d
|
// 44 0f 38 f1 a4 02 00 movbe DWORD PTR [rdx+rax*1+0x0],r12d
|
||||||
// 42 0f 38 f1 8c 22 00 movbe DWORD PTR [rdx+r12*1+0x0],ecx
|
// 42 0f 38 f1 8c 22 00 movbe DWORD PTR [rdx+r12*1+0x0],ecx
|
||||||
// 0f 38 f1 8c 02 00 00 movbe DWORD PTR [rdx + rax * 1 + 0x0], ecx
|
// 0f 38 f1 8c 02 00 00 movbe DWORD PTR [rdx + rax * 1 + 0x0], ecx
|
||||||
mov.is_load = false;
|
mov->is_load = false;
|
||||||
mov.byte_swap = true;
|
mov->byte_swap = true;
|
||||||
i += 3;
|
i += 3;
|
||||||
} else if (p[i] == 0x0F && p[i + 1] == 0x38 && p[i + 2] == 0xF0) {
|
} else if (p[i] == 0x0F && p[i + 1] == 0x38 && p[i + 2] == 0xF0) {
|
||||||
// MOVBE r32, m32 (load)
|
// MOVBE r32, m32 (load)
|
||||||
|
@ -247,8 +247,8 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
// 46 0f 38 f0 a4 22 00 movbe r12d,DWORD PTR [rdx+r12*1+0x0]
|
// 46 0f 38 f0 a4 22 00 movbe r12d,DWORD PTR [rdx+r12*1+0x0]
|
||||||
// 0f 38 f0 8c 02 00 00 movbe ecx,DWORD PTR [rdx+rax*1+0x0]
|
// 0f 38 f0 8c 02 00 00 movbe ecx,DWORD PTR [rdx+rax*1+0x0]
|
||||||
// 0F 38 F0 1C 02 movbe ebx,dword ptr [rdx+rax]
|
// 0F 38 F0 1C 02 movbe ebx,dword ptr [rdx+rax]
|
||||||
mov.is_load = true;
|
mov->is_load = true;
|
||||||
mov.byte_swap = true;
|
mov->byte_swap = true;
|
||||||
i += 3;
|
i += 3;
|
||||||
} else if (p[i] == 0x89) {
|
} else if (p[i] == 0x89) {
|
||||||
// MOV m32, r32 (store)
|
// MOV m32, r32 (store)
|
||||||
|
@ -256,8 +256,8 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
// 44 89 24 02 mov DWORD PTR[rdx + rax * 1], r12d
|
// 44 89 24 02 mov DWORD PTR[rdx + rax * 1], r12d
|
||||||
// 42 89 0c 22 mov DWORD PTR[rdx + r12 * 1], ecx
|
// 42 89 0c 22 mov DWORD PTR[rdx + r12 * 1], ecx
|
||||||
// 89 0c 02 mov DWORD PTR[rdx + rax * 1], ecx
|
// 89 0c 02 mov DWORD PTR[rdx + rax * 1], ecx
|
||||||
mov.is_load = false;
|
mov->is_load = false;
|
||||||
mov.byte_swap = false;
|
mov->byte_swap = false;
|
||||||
++i;
|
++i;
|
||||||
} else if (p[i] == 0x8B) {
|
} else if (p[i] == 0x8B) {
|
||||||
// MOV r32, m32 (load)
|
// MOV r32, m32 (load)
|
||||||
|
@ -266,16 +266,16 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
// 42 8b 0c 22 mov ecx, DWORD PTR[rdx + r12 * 1]
|
// 42 8b 0c 22 mov ecx, DWORD PTR[rdx + r12 * 1]
|
||||||
// 46 8b 24 22 mov r12d, DWORD PTR[rdx + r12 * 1]
|
// 46 8b 24 22 mov r12d, DWORD PTR[rdx + r12 * 1]
|
||||||
// 8b 0c 02 mov ecx, DWORD PTR[rdx + rax * 1]
|
// 8b 0c 02 mov ecx, DWORD PTR[rdx + rax * 1]
|
||||||
mov.is_load = true;
|
mov->is_load = true;
|
||||||
mov.byte_swap = false;
|
mov->byte_swap = false;
|
||||||
++i;
|
++i;
|
||||||
} else if (p[i] == 0xC7) {
|
} else if (p[i] == 0xC7) {
|
||||||
// MOV m32, simm32
|
// MOV m32, simm32
|
||||||
// http://www.asmpedia.org/index.php?title=MOV
|
// http://www.asmpedia.org/index.php?title=MOV
|
||||||
// C7 04 02 02 00 00 00 mov dword ptr [rdx+rax],2
|
// C7 04 02 02 00 00 00 mov dword ptr [rdx+rax],2
|
||||||
mov.is_load = false;
|
mov->is_load = false;
|
||||||
mov.byte_swap = false;
|
mov->byte_swap = false;
|
||||||
mov.is_constant = true;
|
mov->is_constant = true;
|
||||||
++i;
|
++i;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -292,13 +292,13 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
uint8_t mod = (modrm & 0b11000000) >> 6;
|
uint8_t mod = (modrm & 0b11000000) >> 6;
|
||||||
uint8_t reg = (modrm & 0b00111000) >> 3;
|
uint8_t reg = (modrm & 0b00111000) >> 3;
|
||||||
uint8_t rm = (modrm & 0b00000111);
|
uint8_t rm = (modrm & 0b00000111);
|
||||||
mov.value_reg = reg + (rex_r ? 8 : 0);
|
mov->value_reg = reg + (rex_r ? 8 : 0);
|
||||||
mov.mem_has_base = false;
|
mov->mem_has_base = false;
|
||||||
mov.mem_base_reg = 0;
|
mov->mem_base_reg = 0;
|
||||||
mov.mem_has_index = false;
|
mov->mem_has_index = false;
|
||||||
mov.mem_index_reg = 0;
|
mov->mem_index_reg = 0;
|
||||||
mov.mem_scale = 1;
|
mov->mem_scale = 1;
|
||||||
mov.mem_displacement = 0;
|
mov->mem_displacement = 0;
|
||||||
bool has_sib = false;
|
bool has_sib = false;
|
||||||
switch (rm) {
|
switch (rm) {
|
||||||
case 0b100: // SIB
|
case 0b100: // SIB
|
||||||
|
@ -309,17 +309,17 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
// RIP-relative not supported.
|
// RIP-relative not supported.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mov.mem_has_base = true;
|
mov->mem_has_base = true;
|
||||||
mov.mem_base_reg = rm + (rex_b ? 8 : 0);
|
mov->mem_base_reg = rm + (rex_b ? 8 : 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mov.mem_has_base = true;
|
mov->mem_has_base = true;
|
||||||
mov.mem_base_reg = rm + (rex_b ? 8 : 0);
|
mov->mem_base_reg = rm + (rex_b ? 8 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (has_sib) {
|
if (has_sib) {
|
||||||
uint8_t sib = p[i++];
|
uint8_t sib = p[i++];
|
||||||
mov.mem_scale = 1 << ((sib & 0b11000000) >> 8);
|
mov->mem_scale = 1 << ((sib & 0b11000000) >> 8);
|
||||||
uint8_t sib_index = (sib & 0b00111000) >> 3;
|
uint8_t sib_index = (sib & 0b00111000) >> 3;
|
||||||
uint8_t sib_base = (sib & 0b00000111);
|
uint8_t sib_base = (sib & 0b00000111);
|
||||||
switch (sib_index) {
|
switch (sib_index) {
|
||||||
|
@ -327,8 +327,8 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
// No index.
|
// No index.
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mov.mem_has_index = true;
|
mov->mem_has_index = true;
|
||||||
mov.mem_index_reg = sib_index + (rex_x ? 8 : 0);
|
mov->mem_index_reg = sib_index + (rex_x ? 8 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (sib_base) {
|
switch (sib_base) {
|
||||||
|
@ -337,29 +337,28 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov& mov) {
|
||||||
assert_zero(mod);
|
assert_zero(mod);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
mov.mem_has_base = true;
|
mov->mem_has_base = true;
|
||||||
mov.mem_base_reg = sib_base + (rex_b ? 8 : 0);
|
mov->mem_base_reg = sib_base + (rex_b ? 8 : 0);
|
||||||
;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (mod) {
|
switch (mod) {
|
||||||
case 0b00: {
|
case 0b00: {
|
||||||
mov.mem_displacement += 0;
|
mov->mem_displacement += 0;
|
||||||
} break;
|
} break;
|
||||||
case 0b01: {
|
case 0b01: {
|
||||||
mov.mem_displacement += int8_t(p[i++]);
|
mov->mem_displacement += int8_t(p[i++]);
|
||||||
} break;
|
} break;
|
||||||
case 0b10: {
|
case 0b10: {
|
||||||
mov.mem_displacement += xe::load<int32_t>(p + i);
|
mov->mem_displacement += xe::load<int32_t>(p + i);
|
||||||
i += 4;
|
i += 4;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
if (mov.is_constant) {
|
if (mov->is_constant) {
|
||||||
mov.constant = xe::load<int32_t>(p + i);
|
mov->constant = xe::load<int32_t>(p + i);
|
||||||
i += 4;
|
i += 4;
|
||||||
}
|
}
|
||||||
mov.length = i;
|
mov->length = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +390,7 @@ bool MMIOHandler::HandleAccessFault(void* thread_state,
|
||||||
auto rip = GetThreadStateRip(thread_state);
|
auto rip = GetThreadStateRip(thread_state);
|
||||||
auto p = reinterpret_cast<const uint8_t*>(rip);
|
auto p = reinterpret_cast<const uint8_t*>(rip);
|
||||||
DecodedMov mov = {0};
|
DecodedMov mov = {0};
|
||||||
bool decoded = TryDecodeMov(p, mov);
|
bool decoded = TryDecodeMov(p, &mov);
|
||||||
if (!decoded) {
|
if (!decoded) {
|
||||||
XELOGE("Unable to decode MMIO mov at %p", p);
|
XELOGE("Unable to decode MMIO mov at %p", p);
|
||||||
assert_always("Unknown MMIO instruction type");
|
assert_always("Unknown MMIO instruction type");
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace cpu {
|
||||||
|
|
||||||
class MachMMIOHandler : public MMIOHandler {
|
class MachMMIOHandler : public MMIOHandler {
|
||||||
public:
|
public:
|
||||||
MachMMIOHandler(uint8_t* mapping_base);
|
explicit MachMMIOHandler(uint8_t* mapping_base);
|
||||||
~MachMMIOHandler() override;
|
~MachMMIOHandler() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
|
|
||||||
#include "xenia/cpu/module.h"
|
#include "xenia/cpu/module.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream> // NOLINT(readability/streams): should be replaced.
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "xenia/base/threading.h"
|
#include "xenia/base/threading.h"
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
|
@ -138,11 +140,11 @@ Symbol::Status Module::DefineSymbol(Symbol* symbol) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol::Status Module::DefineFunction(Function* symbol) {
|
Symbol::Status Module::DefineFunction(Function* symbol) {
|
||||||
return DefineSymbol((Symbol*)symbol);
|
return DefineSymbol(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol::Status Module::DefineVariable(Symbol* symbol) {
|
Symbol::Status Module::DefineVariable(Symbol* symbol) {
|
||||||
return DefineSymbol((Symbol*)symbol);
|
return DefineSymbol(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::ForEachFunction(std::function<void(Function*)> callback) {
|
void Module::ForEachFunction(std::function<void(Function*)> callback) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ class Processor;
|
||||||
|
|
||||||
class Module {
|
class Module {
|
||||||
public:
|
public:
|
||||||
Module(Processor* processor);
|
explicit Module(Processor* processor);
|
||||||
virtual ~Module();
|
virtual ~Module();
|
||||||
|
|
||||||
Memory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
|
|
|
@ -36,8 +36,11 @@ using PPCContext = xe::cpu::frontend::PPCContext;
|
||||||
|
|
||||||
class BuiltinModule : public Module {
|
class BuiltinModule : public Module {
|
||||||
public:
|
public:
|
||||||
BuiltinModule(Processor* processor) : Module(processor), name_("builtin") {}
|
explicit BuiltinModule(Processor* processor)
|
||||||
|
: Module(processor), name_("builtin") {}
|
||||||
|
|
||||||
const std::string& name() const override { return name_; }
|
const std::string& name() const override { return name_; }
|
||||||
|
|
||||||
bool ContainsAddress(uint32_t address) override {
|
bool ContainsAddress(uint32_t address) override {
|
||||||
return (address & 0xFFFFFFF0) == 0xFFFFFFF0;
|
return (address & 0xFFFFFFF0) == 0xFFFFFFF0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/mutex.h"
|
#include "xenia/base/mutex.h"
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace cpu {
|
||||||
|
|
||||||
class RawModule : public Module {
|
class RawModule : public Module {
|
||||||
public:
|
public:
|
||||||
RawModule(Processor* processor);
|
explicit RawModule(Processor* processor);
|
||||||
~RawModule() override;
|
~RawModule() override;
|
||||||
|
|
||||||
bool LoadFile(uint32_t base_address, const std::wstring& path);
|
bool LoadFile(uint32_t base_address, const std::wstring& path);
|
||||||
|
|
|
@ -25,7 +25,7 @@ DEFINE_bool(debug_symbol_loader, false,
|
||||||
// Must be included after platform_win.h:
|
// Must be included after platform_win.h:
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4091)
|
#pragma warning(disable : 4091)
|
||||||
#include <dbghelp.h>
|
#include <dbghelp.h> // NOLINT(build/include_order)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
typedef DWORD(__stdcall* LPSYMGETOPTIONS)(VOID);
|
typedef DWORD(__stdcall* LPSYMGETOPTIONS)(VOID);
|
||||||
|
@ -115,7 +115,7 @@ bool InitializeStackWalker() {
|
||||||
|
|
||||||
class Win32StackWalker : public StackWalker {
|
class Win32StackWalker : public StackWalker {
|
||||||
public:
|
public:
|
||||||
Win32StackWalker(backend::CodeCache* code_cache) {
|
explicit Win32StackWalker(backend::CodeCache* code_cache) {
|
||||||
// Get the boundaries of the code cache so we can quickly tell if a symbol
|
// Get the boundaries of the code cache so we can quickly tell if a symbol
|
||||||
// is ours or not.
|
// is ours or not.
|
||||||
// We store these globally so that the Sym* callbacks can access them.
|
// We store these globally so that the Sym* callbacks can access them.
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_CPU_SYMBOL_INFO_H_
|
#ifndef XENIA_CPU_SYMBOL_H_
|
||||||
#define XENIA_CPU_SYMBOL_INFO_H_
|
#define XENIA_CPU_SYMBOL_H_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -59,4 +59,4 @@ class Symbol {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_CPU_SYMBOL_INFO_H_
|
#endif // XENIA_CPU_SYMBOL_H_
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_CPU_thread_state_H_
|
#ifndef XENIA_CPU_THREAD_STATE_H_
|
||||||
#define XENIA_CPU_thread_state_H_
|
#define XENIA_CPU_THREAD_STATE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "xenia/cpu/frontend/ppc_context.h"
|
#include "xenia/cpu/frontend/ppc_context.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
@ -70,4 +72,4 @@ class ThreadState {
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_CPU_thread_state_H_
|
#endif // XENIA_CPU_THREAD_STATE_H_
|
||||||
|
|
|
@ -26,9 +26,8 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
using namespace xe::kernel;
|
using xe::cpu::frontend::PPCContext;
|
||||||
|
using xe::kernel::KernelState;
|
||||||
using PPCContext = xe::cpu::frontend::PPCContext;
|
|
||||||
|
|
||||||
void UndefinedImport(PPCContext* ppc_context, KernelState* kernel_state) {
|
void UndefinedImport(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||||
XELOGE("call to undefined import");
|
XELOGE("call to undefined import");
|
||||||
|
@ -52,7 +51,8 @@ bool XexModule::GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
// We just return the value of the optional header.
|
// We just return the value of the optional header.
|
||||||
// Assume that the output pointer points to a uint32_t.
|
// Assume that the output pointer points to a uint32_t.
|
||||||
*(uint32_t*)out_ptr = (uint32_t)opt_header.value;
|
*reinterpret_cast<uint32_t*>(out_ptr) =
|
||||||
|
static_cast<uint32_t>(opt_header.value);
|
||||||
} break;
|
} break;
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
// Pointer to the value on the optional header.
|
// Pointer to the value on the optional header.
|
||||||
|
@ -60,7 +60,8 @@ bool XexModule::GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
// Pointer to the header.
|
// Pointer to the header.
|
||||||
*out_ptr = (void*)((uint8_t*)header + opt_header.offset);
|
*out_ptr =
|
||||||
|
reinterpret_cast<void*>(uintptr_t(header) + opt_header.offset);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ bool XexModule::GetOptHeader(xe_xex2_header_keys key, void** out_ptr) const {
|
||||||
|
|
||||||
const xex2_security_info* XexModule::GetSecurityInfo(
|
const xex2_security_info* XexModule::GetSecurityInfo(
|
||||||
const xex2_header* header) {
|
const xex2_header* header) {
|
||||||
return reinterpret_cast<const xex2_security_info*>((uint8_t*)header +
|
return reinterpret_cast<const xex2_security_info*>(uintptr_t(header) +
|
||||||
header->security_offset);
|
header->security_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +110,8 @@ uint32_t XexModule::GetProcAddress(uint16_t ordinal) const {
|
||||||
*exe_address + pe_export_directory->offset);
|
*exe_address + pe_export_directory->offset);
|
||||||
assert_not_null(e);
|
assert_not_null(e);
|
||||||
|
|
||||||
uint32_t* function_table = (uint32_t*)((uint8_t*)e + e->AddressOfFunctions);
|
uint32_t* function_table =
|
||||||
|
reinterpret_cast<uint32_t*>(uintptr_t(e) + e->AddressOfFunctions);
|
||||||
|
|
||||||
if (ordinal < e->NumberOfFunctions) {
|
if (ordinal < e->NumberOfFunctions) {
|
||||||
return xex_security_info()->load_address + function_table[ordinal];
|
return xex_security_info()->load_address + function_table[ordinal];
|
||||||
|
@ -135,20 +137,22 @@ uint32_t XexModule::GetProcAddress(const char* name) const {
|
||||||
assert_not_null(e);
|
assert_not_null(e);
|
||||||
|
|
||||||
// e->AddressOfX RVAs are relative to the IMAGE_EXPORT_DIRECTORY!
|
// e->AddressOfX RVAs are relative to the IMAGE_EXPORT_DIRECTORY!
|
||||||
uint32_t* function_table = (uint32_t*)((uint64_t)e + e->AddressOfFunctions);
|
uint32_t* function_table =
|
||||||
|
reinterpret_cast<uint32_t*>(uintptr_t(e) + e->AddressOfFunctions);
|
||||||
|
|
||||||
// Names relative to directory
|
// Names relative to directory
|
||||||
uint32_t* name_table = (uint32_t*)((uint64_t)e + e->AddressOfNames);
|
uint32_t* name_table =
|
||||||
|
reinterpret_cast<uint32_t*>(uintptr_t(e) + e->AddressOfNames);
|
||||||
|
|
||||||
// Table of ordinals (by name)
|
// Table of ordinals (by name)
|
||||||
uint16_t* ordinal_table = (uint16_t*)((uint64_t)e + e->AddressOfNameOrdinals);
|
uint16_t* ordinal_table =
|
||||||
|
reinterpret_cast<uint16_t*>(uintptr_t(e) + e->AddressOfNameOrdinals);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < e->NumberOfNames; i++) {
|
for (uint32_t i = 0; i < e->NumberOfNames; i++) {
|
||||||
const char* fn_name = (const char*)((uint64_t)e + name_table[i]);
|
auto fn_name = reinterpret_cast<const char*>(uintptr_t(e) + name_table[i]);
|
||||||
uint16_t ordinal = ordinal_table[i];
|
uint16_t ordinal = ordinal_table[i];
|
||||||
uint32_t addr = *exe_address + function_table[ordinal];
|
uint32_t addr = *exe_address + function_table[ordinal];
|
||||||
|
if (!std::strcmp(name, fn_name)) {
|
||||||
if (!strcmp(name, fn_name)) {
|
|
||||||
// We have a match!
|
// We have a match!
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
@ -170,17 +174,17 @@ bool XexModule::ApplyPatch(XexModule* module) {
|
||||||
// Grab the delta descriptor and get to work.
|
// Grab the delta descriptor and get to work.
|
||||||
xex2_opt_delta_patch_descriptor* patch_header = nullptr;
|
xex2_opt_delta_patch_descriptor* patch_header = nullptr;
|
||||||
GetOptHeader(header, XEX_HEADER_DELTA_PATCH_DESCRIPTOR,
|
GetOptHeader(header, XEX_HEADER_DELTA_PATCH_DESCRIPTOR,
|
||||||
(void**)&patch_header);
|
reinterpret_cast<void**>(&patch_header));
|
||||||
assert_not_null(patch_header);
|
assert_not_null(patch_header);
|
||||||
|
|
||||||
// TODO!
|
// TODO(benvanik): patching code!
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XexModule::Load(const std::string& name, const std::string& path,
|
bool XexModule::Load(const std::string& name, const std::string& path,
|
||||||
const void* xex_addr, size_t xex_length) {
|
const void* xex_addr, size_t xex_length) {
|
||||||
// TODO: Move loading code here
|
// TODO(DrChat): Move loading code here.
|
||||||
xex_ = xe_xex2_load(memory(), xex_addr, xex_length, {0});
|
xex_ = xe_xex2_load(memory(), xex_addr, xex_length, {0});
|
||||||
if (!xex_) {
|
if (!xex_) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -210,7 +214,7 @@ bool XexModule::Load(const std::string& name, const std::string& path,
|
||||||
|
|
||||||
// Scan and find the low/high addresses.
|
// Scan and find the low/high addresses.
|
||||||
// All code sections are continuous, so this should be easy.
|
// All code sections are continuous, so this should be easy.
|
||||||
// TODO: Use the new xex header to do this.
|
// TODO(DrChat): Use the new xex header to do this.
|
||||||
low_address_ = UINT_MAX;
|
low_address_ = UINT_MAX;
|
||||||
high_address_ = 0;
|
high_address_ = 0;
|
||||||
for (uint32_t n = 0, i = 0; n < old_header->section_count; n++) {
|
for (uint32_t n = 0, i = 0; n < old_header->section_count; n++) {
|
||||||
|
@ -252,14 +256,13 @@ bool XexModule::Load(const std::string& name, const std::string& path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto libraries =
|
auto libraries_ptr = reinterpret_cast<uint8_t*>(opt_import_header) +
|
||||||
(uint8_t*)opt_import_header + opt_import_header->string_table_size + 12;
|
opt_import_header->string_table_size + 12;
|
||||||
uint32_t library_offset = 0;
|
uint32_t library_offset = 0;
|
||||||
for (uint32_t i = 0; i < opt_import_header->library_count; i++) {
|
for (uint32_t i = 0; i < opt_import_header->library_count; i++) {
|
||||||
auto library = reinterpret_cast<xex2_import_library*>((uint8_t*)libraries +
|
auto library =
|
||||||
library_offset);
|
reinterpret_cast<xex2_import_library*>(libraries_ptr + library_offset);
|
||||||
SetupLibraryImports(string_table[library->name_index], library);
|
SetupLibraryImports(string_table[library->name_index], library);
|
||||||
|
|
||||||
library_offset += library->size;
|
library_offset += library->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,18 +11,19 @@
|
||||||
#define XENIA_CPU_XEX_MODULE_H_
|
#define XENIA_CPU_XEX_MODULE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/cpu/module.h"
|
#include "xenia/cpu/module.h"
|
||||||
#include "xenia/kernel/util/xex2.h"
|
#include "xenia/kernel/util/xex2.h"
|
||||||
#include "xenia/kernel/util/xex2_info.h"
|
#include "xenia/kernel/util/xex2_info.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
// KernelState forward decl.
|
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
class KernelState;
|
class KernelState;
|
||||||
}
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
class Runtime;
|
class Runtime;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace xe {
|
||||||
namespace debug {
|
namespace debug {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
int main(std::vector<std::wstring>& args) {
|
int main(const std::vector<std::wstring>& args) {
|
||||||
auto app = Application::Create();
|
auto app = Application::Create();
|
||||||
app->loop()->AwaitQuit();
|
app->loop()->AwaitQuit();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -33,13 +33,6 @@ DEFINE_double(time_scalar, 1.0,
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
using namespace xe::apu;
|
|
||||||
using namespace xe::cpu;
|
|
||||||
using namespace xe::gpu;
|
|
||||||
using namespace xe::hid;
|
|
||||||
using namespace xe::ui;
|
|
||||||
using namespace xe::vfs;
|
|
||||||
|
|
||||||
Emulator::Emulator(const std::wstring& command_line)
|
Emulator::Emulator(const std::wstring& command_line)
|
||||||
: command_line_(command_line) {}
|
: command_line_(command_line) {}
|
||||||
|
|
||||||
|
@ -107,7 +100,7 @@ X_STATUS Emulator::Setup(ui::Window* display_window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the CPU.
|
// Initialize the CPU.
|
||||||
processor_ = std::make_unique<Processor>(
|
processor_ = std::make_unique<xe::cpu::Processor>(
|
||||||
memory_.get(), export_resolver_.get(), debugger_.get());
|
memory_.get(), export_resolver_.get(), debugger_.get());
|
||||||
|
|
||||||
// Initialize the APU.
|
// Initialize the APU.
|
||||||
|
@ -116,7 +109,7 @@ X_STATUS Emulator::Setup(ui::Window* display_window) {
|
||||||
return X_STATUS_NOT_IMPLEMENTED;
|
return X_STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
xma_decoder_ = std::make_unique<XmaDecoder>(this);
|
xma_decoder_ = std::make_unique<xe::apu::XmaDecoder>(this);
|
||||||
|
|
||||||
// Initialize the GPU.
|
// Initialize the GPU.
|
||||||
graphics_system_ = xe::gpu::GraphicsSystem::Create(this);
|
graphics_system_ = xe::gpu::GraphicsSystem::Create(this);
|
||||||
|
@ -140,10 +133,10 @@ X_STATUS Emulator::Setup(ui::Window* display_window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bring up the virtual filesystem used by the kernel.
|
// Bring up the virtual filesystem used by the kernel.
|
||||||
file_system_ = std::make_unique<VirtualFileSystem>();
|
file_system_ = std::make_unique<xe::vfs::VirtualFileSystem>();
|
||||||
|
|
||||||
// Shared kernel state.
|
// Shared kernel state.
|
||||||
kernel_state_ = std::make_unique<kernel::KernelState>(this);
|
kernel_state_ = std::make_unique<xe::kernel::KernelState>(this);
|
||||||
|
|
||||||
// Setup the core components.
|
// Setup the core components.
|
||||||
if (!processor_->Setup()) {
|
if (!processor_->Setup()) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace xe {
|
||||||
|
|
||||||
class Emulator {
|
class Emulator {
|
||||||
public:
|
public:
|
||||||
Emulator(const std::wstring& command_line);
|
explicit Emulator(const std::wstring& command_line);
|
||||||
~Emulator();
|
~Emulator();
|
||||||
|
|
||||||
const std::wstring& command_line() const { return command_line_; }
|
const std::wstring& command_line() const { return command_line_; }
|
||||||
|
|
|
@ -2187,7 +2187,7 @@ void DrawUI(xe::ui::Window* window, TracePlayer& player, Memory* memory) {
|
||||||
void ImImpl_Setup();
|
void ImImpl_Setup();
|
||||||
void ImImpl_Shutdown();
|
void ImImpl_Shutdown();
|
||||||
|
|
||||||
int trace_viewer_main(std::vector<std::wstring>& args) {
|
int trace_viewer_main(const std::vector<std::wstring>& args) {
|
||||||
// Create the emulator but don't initialize so we can setup the window.
|
// Create the emulator but don't initialize so we can setup the window.
|
||||||
auto emulator = std::make_unique<Emulator>(L"");
|
auto emulator = std::make_unique<Emulator>(L"");
|
||||||
|
|
||||||
|
|
|
@ -427,10 +427,10 @@ int xe_xex2_read_header(const uint8_t* addr, const size_t length,
|
||||||
}
|
}
|
||||||
|
|
||||||
int xe_xex2_decrypt_key(xe_xex2_header_t* header) {
|
int xe_xex2_decrypt_key(xe_xex2_header_t* header) {
|
||||||
const static uint8_t xe_xex2_retail_key[16] = {
|
static const uint8_t xe_xex2_retail_key[16] = {
|
||||||
0x20, 0xB1, 0x85, 0xA5, 0x9D, 0x28, 0xFD, 0xC3,
|
0x20, 0xB1, 0x85, 0xA5, 0x9D, 0x28, 0xFD, 0xC3,
|
||||||
0x40, 0x58, 0x3F, 0xBB, 0x08, 0x96, 0xBF, 0x91};
|
0x40, 0x58, 0x3F, 0xBB, 0x08, 0x96, 0xBF, 0x91};
|
||||||
const static uint8_t xe_xex2_devkit_key[16] = {
|
static const uint8_t xe_xex2_devkit_key[16] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
|
|
@ -308,25 +308,25 @@ DECLARE_XAM_EXPORT(NetDll_WSAResetEvent,
|
||||||
|
|
||||||
struct XnAddrStatus {
|
struct XnAddrStatus {
|
||||||
// Address acquisition is not yet complete
|
// Address acquisition is not yet complete
|
||||||
const static uint32_t XNET_GET_XNADDR_PENDING = 0x00000000;
|
static const uint32_t XNET_GET_XNADDR_PENDING = 0x00000000;
|
||||||
// XNet is uninitialized or no debugger found
|
// XNet is uninitialized or no debugger found
|
||||||
const static uint32_t XNET_GET_XNADDR_NONE = 0x00000001;
|
static const uint32_t XNET_GET_XNADDR_NONE = 0x00000001;
|
||||||
// Host has ethernet address (no IP address)
|
// Host has ethernet address (no IP address)
|
||||||
const static uint32_t XNET_GET_XNADDR_ETHERNET = 0x00000002;
|
static const uint32_t XNET_GET_XNADDR_ETHERNET = 0x00000002;
|
||||||
// Host has statically assigned IP address
|
// Host has statically assigned IP address
|
||||||
const static uint32_t XNET_GET_XNADDR_STATIC = 0x00000004;
|
static const uint32_t XNET_GET_XNADDR_STATIC = 0x00000004;
|
||||||
// Host has DHCP assigned IP address
|
// Host has DHCP assigned IP address
|
||||||
const static uint32_t XNET_GET_XNADDR_DHCP = 0x00000008;
|
static const uint32_t XNET_GET_XNADDR_DHCP = 0x00000008;
|
||||||
// Host has PPPoE assigned IP address
|
// Host has PPPoE assigned IP address
|
||||||
const static uint32_t XNET_GET_XNADDR_PPPOE = 0x00000010;
|
static const uint32_t XNET_GET_XNADDR_PPPOE = 0x00000010;
|
||||||
// Host has one or more gateways configured
|
// Host has one or more gateways configured
|
||||||
const static uint32_t XNET_GET_XNADDR_GATEWAY = 0x00000020;
|
static const uint32_t XNET_GET_XNADDR_GATEWAY = 0x00000020;
|
||||||
// Host has one or more DNS servers configured
|
// Host has one or more DNS servers configured
|
||||||
const static uint32_t XNET_GET_XNADDR_DNS = 0x00000040;
|
static const uint32_t XNET_GET_XNADDR_DNS = 0x00000040;
|
||||||
// Host is currently connected to online service
|
// Host is currently connected to online service
|
||||||
const static uint32_t XNET_GET_XNADDR_ONLINE = 0x00000080;
|
static const uint32_t XNET_GET_XNADDR_ONLINE = 0x00000080;
|
||||||
// Network configuration requires troubleshooting
|
// Network configuration requires troubleshooting
|
||||||
const static uint32_t XNET_GET_XNADDR_TROUBLESHOOT = 0x00008000;
|
static const uint32_t XNET_GET_XNADDR_TROUBLESHOOT = 0x00008000;
|
||||||
};
|
};
|
||||||
|
|
||||||
dword_result_t NetDll_XNetGetTitleXnAddr(dword_t caller,
|
dword_result_t NetDll_XNetGetTitleXnAddr(dword_t caller,
|
||||||
|
|
|
@ -127,7 +127,7 @@ int Memory::Initialize() {
|
||||||
// we pick, so try a few times.
|
// we pick, so try a few times.
|
||||||
mapping_base_ = 0;
|
mapping_base_ = 0;
|
||||||
for (size_t n = 32; n < 64; n++) {
|
for (size_t n = 32; n < 64; n++) {
|
||||||
uint8_t* mapping_base = (uint8_t*)(1ull << n);
|
auto mapping_base = reinterpret_cast<uint8_t*>(1ull << n);
|
||||||
if (!MapViews(mapping_base)) {
|
if (!MapViews(mapping_base)) {
|
||||||
mapping_base_ = mapping_base;
|
mapping_base_ = mapping_base;
|
||||||
break;
|
break;
|
||||||
|
@ -192,7 +192,7 @@ int Memory::Initialize() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct {
|
static const struct {
|
||||||
uint64_t virtual_address_start;
|
uint64_t virtual_address_start;
|
||||||
uint64_t virtual_address_end;
|
uint64_t virtual_address_end;
|
||||||
uint64_t target_address;
|
uint64_t target_address;
|
||||||
|
|
|
@ -165,11 +165,11 @@ class Memory {
|
||||||
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
||||||
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
||||||
return virtual_membase_ + guest_address;
|
return virtual_membase_ + guest_address;
|
||||||
};
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T TranslateVirtual(uint32_t guest_address) const {
|
inline T TranslateVirtual(uint32_t guest_address) const {
|
||||||
return reinterpret_cast<T>(virtual_membase_ + guest_address);
|
return reinterpret_cast<T>(virtual_membase_ + guest_address);
|
||||||
};
|
}
|
||||||
|
|
||||||
inline uint8_t* physical_membase() const { return physical_membase_; }
|
inline uint8_t* physical_membase() const { return physical_membase_; }
|
||||||
inline uint8_t* TranslatePhysical(uint32_t guest_address) const {
|
inline uint8_t* TranslatePhysical(uint32_t guest_address) const {
|
||||||
|
|
|
@ -7,10 +7,15 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/base/logging.h"
|
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// NOTE: this must be included before microprofile as macro expansion needs
|
||||||
|
// XELOGI.
|
||||||
|
#include "xenia/base/logging.h"
|
||||||
|
|
||||||
|
// NOTE: microprofile must be setup first, before profiling.h is included.
|
||||||
#define MICROPROFILE_ENABLED 1
|
#define MICROPROFILE_ENABLED 1
|
||||||
#define MICROPROFILEUI_ENABLED 1
|
#define MICROPROFILEUI_ENABLED 1
|
||||||
#define MICROPROFILE_IMPL 1
|
#define MICROPROFILE_IMPL 1
|
||||||
|
@ -22,10 +27,10 @@
|
||||||
#define MICROPROFILE_WEBSERVER 1
|
#define MICROPROFILE_WEBSERVER 1
|
||||||
#define MICROPROFILE_DEBUG 0
|
#define MICROPROFILE_DEBUG 0
|
||||||
#if MICROPROFILE_WEBSERVER
|
#if MICROPROFILE_WEBSERVER
|
||||||
#include <winsock.h>
|
#include <winsock.h> // NOLINT(build/include_order)
|
||||||
#endif // MICROPROFILE_WEBSERVER
|
#endif // MICROPROFILE_WEBSERVER
|
||||||
#include <microprofile/microprofile.h>
|
#include "third_party/microprofile/microprofile.h"
|
||||||
#include <microprofile/microprofileui.h>
|
#include "third_party/microprofile/microprofileui.h"
|
||||||
|
|
||||||
#include "xenia/profiling.h"
|
#include "xenia/profiling.h"
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ bool DiscImageDevice::Initialize() {
|
||||||
|
|
||||||
DiscImageDevice::Error DiscImageDevice::Verify(ParseState& state) {
|
DiscImageDevice::Error DiscImageDevice::Verify(ParseState& state) {
|
||||||
// Find sector 32 of the game partition - try at a few points.
|
// Find sector 32 of the game partition - try at a few points.
|
||||||
const static size_t likely_offsets[] = {
|
static const size_t likely_offsets[] = {
|
||||||
0x00000000, 0x0000FB20, 0x00020600, 0x0FD90000,
|
0x00000000, 0x0000FB20, 0x00020600, 0x0FD90000,
|
||||||
};
|
};
|
||||||
bool magic_found = false;
|
bool magic_found = false;
|
||||||
|
|
|
@ -76,7 +76,10 @@ typedef uint32_t X_STATUS;
|
||||||
// Windows is a weird place.
|
// Windows is a weird place.
|
||||||
typedef uint32_t X_RESULT;
|
typedef uint32_t X_RESULT;
|
||||||
#define X_FACILITY_WIN32 7
|
#define X_FACILITY_WIN32 7
|
||||||
#define X_RESULT_FROM_WIN32(x) x //((X_RESULT)(x) <= 0 ? ((X_RESULT)(x)) : ((X_RESULT) (((x) & 0x0000FFFF) | (X_FACILITY_WIN32 << 16) | 0x80000000)))
|
#define X_RESULT_FROM_WIN32(x) x
|
||||||
|
// Maybe X_RESULT_FROM_WIN32 is this instead?:
|
||||||
|
// ((X_RESULT)(x) <= 0 ? ((X_RESULT)(x)) :
|
||||||
|
// ((X_RESULT) (((x) & 0x0000FFFF) | (X_FACILITY_WIN32 << 16) | 0x80000000)))
|
||||||
#define X_ERROR_SUCCESS X_RESULT_FROM_WIN32(0x00000000L)
|
#define X_ERROR_SUCCESS X_RESULT_FROM_WIN32(0x00000000L)
|
||||||
#define X_ERROR_FILE_NOT_FOUND X_RESULT_FROM_WIN32(0x00000002L)
|
#define X_ERROR_FILE_NOT_FOUND X_RESULT_FROM_WIN32(0x00000002L)
|
||||||
#define X_ERROR_PATH_NOT_FOUND X_RESULT_FROM_WIN32(0x00000003L)
|
#define X_ERROR_PATH_NOT_FOUND X_RESULT_FROM_WIN32(0x00000003L)
|
||||||
|
@ -115,7 +118,7 @@ typedef uint32_t X_HRESULT;
|
||||||
#define X_MEM_NOZERO 0x00800000
|
#define X_MEM_NOZERO 0x00800000
|
||||||
#define X_MEM_LARGE_PAGES 0x20000000
|
#define X_MEM_LARGE_PAGES 0x20000000
|
||||||
#define X_MEM_HEAP 0x40000000
|
#define X_MEM_HEAP 0x40000000
|
||||||
#define X_MEM_16MB_PAGES 0x80000000 // from Valve SDK
|
#define X_MEM_16MB_PAGES 0x80000000 // from Valve SDK
|
||||||
|
|
||||||
// PAGE_*, used by NtAllocateVirtualMemory
|
// PAGE_*, used by NtAllocateVirtualMemory
|
||||||
#define X_PAGE_NOACCESS 0x00000001
|
#define X_PAGE_NOACCESS 0x00000001
|
||||||
|
@ -338,8 +341,10 @@ struct X_LIST_ENTRY {
|
||||||
|
|
||||||
// Assumes X_LIST_ENTRY is within guest memory!
|
// Assumes X_LIST_ENTRY is within guest memory!
|
||||||
void initialize(uint8_t* virtual_membase) {
|
void initialize(uint8_t* virtual_membase) {
|
||||||
flink_ptr = (uint32_t)((uint8_t*)this - virtual_membase);
|
flink_ptr = static_cast<uint32_t>(reinterpret_cast<uint8_t*>(this) -
|
||||||
blink_ptr = (uint32_t)((uint8_t*)this - virtual_membase);
|
virtual_membase);
|
||||||
|
blink_ptr = static_cast<uint32_t>(reinterpret_cast<uint8_t*>(this) -
|
||||||
|
virtual_membase);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert_size(X_LIST_ENTRY, 8);
|
static_assert_size(X_LIST_ENTRY, 8);
|
||||||
|
|
Loading…
Reference in New Issue