[CPU] MMIO: Arm64, load register writes + exception cleanup
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
class Exception;
|
||||
@@ -93,6 +94,61 @@ class MMIOHandler {
|
||||
static MMIOHandler* global_handler_;
|
||||
|
||||
xe::global_critical_region global_critical_region_;
|
||||
|
||||
private:
|
||||
struct DecodedLoadStore {
|
||||
// Matches the Xn/Wn register number for 0 reads and ignored writes in many
|
||||
// usage cases.
|
||||
static constexpr uint8_t kArm64RegZero = 31;
|
||||
|
||||
// Matches the actual register number encoding for an SP base in AArch64
|
||||
// load and store instructions.
|
||||
static constexpr uint8_t kArm64MemBaseRegSp = kArm64RegZero;
|
||||
|
||||
static constexpr uint8_t kArm64ValueRegX0 = 0;
|
||||
static constexpr uint8_t kArm64ValueRegZero =
|
||||
kArm64ValueRegX0 + kArm64RegZero;
|
||||
static constexpr uint8_t kArm64ValueRegV0 = 32;
|
||||
|
||||
size_t length;
|
||||
// Inidicates this is a load (or conversely a store).
|
||||
bool is_load;
|
||||
// Indicates the memory must be swapped.
|
||||
bool byte_swap;
|
||||
// Source (for store) or target (for load) register.
|
||||
// For x86-64:
|
||||
// AX CX DX BX SP BP SI DI // REX.R=0
|
||||
// R8 R9 R10 R11 R12 R13 R14 R15 // REX.R=1
|
||||
// For AArch64:
|
||||
// - kArm64ValueRegX0 + [0...30]: Xn (Wn for 32 bits - upper 32 bits of Xn
|
||||
// are zeroed on Wn write).
|
||||
// - kArm64ValueRegZero: Zero constant for register read, ignored register
|
||||
// write (though memory must still be accessed - a MMIO load may have side
|
||||
// effects even if the result is discarded).
|
||||
// - kArm64ValueRegV0 + [0...31]: Vn (Sn for 32 bits).
|
||||
uint8_t value_reg;
|
||||
// [base + (index * scale) + displacement]
|
||||
bool mem_has_base;
|
||||
// On AArch64, if mem_base_reg is kArm64MemBaseRegSp, the base register is
|
||||
// SP, not Xn.
|
||||
uint8_t mem_base_reg;
|
||||
// For AArch64 pre- and post-indexing. In case of a load, the base register
|
||||
// is written back after the loaded data is written to the register,
|
||||
// overwriting the value register if it's the same.
|
||||
bool mem_base_writeback;
|
||||
int32_t mem_base_writeback_offset;
|
||||
bool mem_has_index;
|
||||
uint8_t mem_index_reg;
|
||||
uint8_t mem_index_size;
|
||||
bool mem_index_sign_extend;
|
||||
uint8_t mem_scale;
|
||||
ptrdiff_t mem_displacement;
|
||||
bool is_constant;
|
||||
int32_t constant;
|
||||
};
|
||||
|
||||
static bool TryDecodeLoadStore(const uint8_t* p,
|
||||
DecodedLoadStore& decoded_out);
|
||||
};
|
||||
|
||||
} // namespace cpu
|
||||
|
||||
Reference in New Issue
Block a user