Adding instruction table and basic PPC state.

Can decode a single instruction.
This commit is contained in:
Ben Vanik
2013-01-13 21:25:28 -08:00
parent 099e37490a
commit bfec194533
12 changed files with 715 additions and 3 deletions

View File

@@ -29,7 +29,7 @@ xe_memory_ref xe_memory_retain(xe_memory_ref memory);
void xe_memory_release(xe_memory_ref memory);
size_t xe_memory_get_length(xe_memory_ref memory);
void *xe_memory_addr(xe_memory_ref memory, uint32_t guest_addr);
uint8_t *xe_memory_addr(xe_memory_ref memory, uint32_t guest_addr);
#endif // XENIA_CORE_MEMORY_H_

18
include/xenia/cpu/ppc.h Normal file
View File

@@ -0,0 +1,18 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_PPC_H_
#define XENIA_CPU_PPC_H_
#include <xenia/common.h>
#include <xenia/cpu/ppc/instr.h>
#include <xenia/cpu/ppc/state.h>
#endif // XENIA_CPU_PPC_H_

View File

@@ -0,0 +1,137 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_PPC_INSTR_H_
#define XENIA_CPU_PPC_INSTR_H_
#include <xenia/common.h>
typedef enum {
kXEPPCInstrFormatI = 0,
kXEPPCInstrFormatB = 1,
kXEPPCInstrFormatSC = 2,
kXEPPCInstrFormatD = 3,
kXEPPCInstrFormatDS = 4,
kXEPPCInstrFormatX = 5,
kXEPPCInstrFormatXL = 6,
kXEPPCInstrFormatXFX = 7,
kXEPPCInstrFormatXFL = 8,
kXEPPCInstrFormatXS = 9,
kXEPPCInstrFormatXO = 10,
kXEPPCInstrFormatA = 11,
kXEPPCInstrFormatM = 12,
kXEPPCInstrFormatMD = 13,
kXEPPCInstrFormatMDS = 14,
kXEPPCInstrFormatVA = 15,
kXEPPCInstrFormatVX = 16,
kXEPPCInstrFormatVXR = 17,
} xe_ppc_instr_format_e;
typedef enum {
kXEPPCInstrTypeGeneral = (1 << 0),
kXEPPCInstrTypeBranch = (1 << 1),
kXEPPCInstrTypeBranchCond = kXEPPCInstrTypeBranch | (1 << 2),
kXEPPCInstrTypeBranchAlways = kXEPPCInstrTypeBranch | (1 << 3),
kXEPPCInstrTypeSyscall = (1 << 4),
} xe_ppc_instr_type_e;
typedef enum {
kXEPPCInstrFlagReserved = 0,
} xe_ppc_instr_flag_e;
struct xe_ppc_instr_type;
typedef struct xe_ppc_instr_type xe_ppc_instr_type_t;
typedef struct {
xe_ppc_instr_type_t *type;
uint32_t address;
union {
uint32_t code;
// kXEPPCInstrFormatI
struct {
uint32_t LK : 1;
uint32_t AA : 1;
uint32_t LI : 24;
uint32_t OPCD : 6;
} I;
// kXEPPCInstrFormatB
struct {
uint32_t LK : 1;
uint32_t AA : 1;
uint32_t BD : 14;
uint32_t BI : 5;
uint32_t BO : 5;
uint32_t OPCD : 6;
} B;
// kXEPPCInstrFormatSC
struct {
uint32_t SIMM : 16;
uint32_t A : 5;
uint32_t D : 5;
uint32_t OPCD : 6;
} D;
// kXEPPCInstrFormatDS
struct {
uint32_t : 2;
uint32_t ds : 14;
uint32_t A : 5;
uint32_t S : 5;
uint32_t OPCD : 6;
} DS;
// kXEPPCInstrFormatX
// kXEPPCInstrFormatXL
struct {
uint32_t : 1;
uint32_t : 10;
uint32_t spr : 10;
uint32_t D : 5;
uint32_t OPCD : 6;
} XFX;
// kXEPPCInstrFormatXFL
// kXEPPCInstrFormatXS
// kXEPPCInstrFormatXO
// kXEPPCInstrFormatA
// kXEPPCInstrFormatM
// kXEPPCInstrFormatMD
// kXEPPCInstrFormatMDS
// kXEPPCInstrFormatVA
// kXEPPCInstrFormatVX
// kXEPPCInstrFormatVXR
} data;
} xe_ppc_instr_t;
typedef struct {
xe_ppc_instr_t instr;
// TODO(benvanik): registers changed, special bits, etc
} xe_ppc_dec_instr_t;
typedef int (*xe_ppc_emit_fn)(/* emit context */ xe_ppc_instr_t *instr);
struct xe_ppc_instr_type {
uint32_t opcode;
uint32_t format; // xe_ppc_instr_format_e
uint32_t type; // xe_ppc_instr_type_e
uint32_t flags; // xe_ppc_instr_flag_e
char name[16];
xe_ppc_emit_fn emit;
};
xe_ppc_instr_type_t *xe_ppc_get_instr_type(uint32_t code);
int xe_ppc_register_instr_emit(uint32_t code, xe_ppc_emit_fn emit);
#endif // XENIA_CPU_PPC_INSTR_H_

View File

@@ -0,0 +1,111 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_PPC_STATE_H_
#define XENIA_CPU_PPC_STATE_H_
#include <xenia/common.h>
typedef struct XECACHEALIGN64 {
uint64_t r[32]; // General purpose registers
xefloat4_t v[128]; // VMX128 vector registers
double f[32]; // Floating-point registers
uint32_t pc; // Current PC (CIA)
uint32_t npc; // Next PC (NIA)
uint64_t xer; // XER register
uint64_t lr; // Link register
uint64_t ctr; // Count register
union {
uint32_t value;
struct {
uint8_t lt :1; // Negative (LT) - result is negative
uint8_t gt :1; // Positive (GT) - result is positive (and not zero)
uint8_t eq :1; // Zero (EQ) - result is zero or a stwcx/stdcx completed successfully
uint8_t so :1; // Summary Overflow (SO) - copy of XER[SO]
} cr0;
struct {
uint8_t fx :1; // FP exception summary - copy of FPSCR[FX]
uint8_t fex :1; // FP enabled exception summary - copy of FPSCR[FEX]
uint8_t vx :1; // FP invalid operation exception summary - copy of FPSCR[VX]
uint8_t ox :1; // FP overflow exception - copy of FPSCR[OX]
} cr1;
} cr; // Condition register
union {
uint32_t value;
struct {
uint8_t fx :1; // FP exception summary -- sticky
uint8_t fex :1; // FP enabled exception summary
uint8_t vx :1; // FP invalid operation exception summary
uint8_t ox :1; // FP overflow exception -- sticky
uint8_t ux :1; // FP underflow exception -- sticky
uint8_t zx :1; // FP zero divide exception -- sticky
uint8_t xx :1; // FP inexact exception -- sticky
uint8_t vxsnan :1; // FP invalid op exception: SNaN -- sticky
uint8_t vxisi :1; // FP invalid op exception: infinity - infinity -- sticky
uint8_t vxidi :1; // FP invalid op exception: infinity / infinity -- sticky
uint8_t vxzdz :1; // FP invalid op exception: 0 / 0 -- sticky
uint8_t vximz :1; // FP invalid op exception: infinity * 0 -- sticky
uint8_t vxvc :1; // FP invalid op exception: invalid compare -- sticky
uint8_t fr :1; // FP fraction rounded
uint8_t fi :1; // FP fraction inexact
uint8_t fprf_c :1; // FP result class
uint8_t fprf_lt :1; // FP result less than or negative (FL or <)
uint8_t fprf_gt :1; // FP result greater than or positive (FG or >)
uint8_t fprf_eq :1; // FP result equal or zero (FE or =)
uint8_t fprf_un :1; // FP result unordered or NaN (FU or ?)
uint8_t reserved :1;
uint8_t vxsoft :1; // FP invalid op exception: software request -- sticky
uint8_t vxsqrt :1; // FP invalid op exception: invalid sqrt -- sticky
uint8_t vxcvi :1; // FP invalid op exception: invalid integer convert -- sticky
uint8_t ve :1; // FP invalid op exception enable
uint8_t oe :1; // IEEE floating-point overflow exception enable
uint8_t ue :1; // IEEE floating-point underflow exception enable
uint8_t ze :1; // IEEE floating-point zero divide exception enable
uint8_t xe :1; // IEEE floating-point inexact exception enable
uint8_t ni :1; // Floating-point non-IEEE mode
uint8_t rn :2; // FP rounding control: 00 = nearest
// 01 = toward zero
// 10 = toward +infinity
// 11 = toward -infinity
} bits;
} fpscr; // Floating-point status and control register
} xe_ppc_registers_t;
typedef struct {
xe_ppc_registers_t registers;
} xe_ppc_state_t;
namespace XE_PPC_FPRF {
enum XE_PPC_FPRF_e {
QUIET_NAN = 0x00088000,
NEG_INFINITY = 0x00090000,
NEG_NORMALIZED = 0x00010000,
NEG_DENORMALIZED = 0x00018000,
NEG_ZERO = 0x00048000,
POS_ZERO = 0x00040000,
POS_DENORMALIZED = 0x00028000,
POS_NORMALIZED = 0x00020000,
POS_INFINITY = 0x000A0000,
};
} // XE_PPC_FPRF
uint32_t xe_ppc_get_fprf(const xe_ppc_registers_t *r) {
return r->fpscr.value & 0x000F8000;
}
void xe_ppc_set_fprf(xe_ppc_registers_t *r, const uint32_t v) {
r->fpscr.value = (r->fpscr.value & ~0x000F8000) | v;
}
#endif // XENIA_CPU_PPC_STATE_H_

View File

@@ -95,6 +95,9 @@ typedef XECACHEALIGN volatile void xe_aligned_void_t;
#endif // GNUC
#endif // !MIN
#define XEBITMASK(a, b) (((unsigned) -1 >> (31 - (b))) & ~((1U << (a)) - 1))
#define XESELECTBITS(value, a, b) ((value & XEBITMASK(a, b)) >> a)
#define XEFAIL() goto XECLEANUP
#define XEEXPECT(expr) if (!(expr) ) { goto XECLEANUP; }
#define XEEXPECTTRUE(expr) if (!(expr) ) { goto XECLEANUP; }
@@ -106,4 +109,21 @@ typedef XECACHEALIGN volatile void xe_aligned_void_t;
#define XEIGNORE(expr) do { (void)(expr); } while(0)
typedef struct XECACHEALIGN {
union {
struct {
float x;
float y;
float z;
float w;
};
float f4[4];
struct {
uint64_t low;
uint64_t high;
};
};
} xefloat4_t;
#endif // XENIA_TYPES_H_