* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (__CPU_PPC_H__)
#define __CPU_PPC_H__
#if defined(TARGET_PPCEMB)
/* Specific definitions for PowerPC embedded */
/* BookE have 36 bits physical address space */
-#define TARGET_PHYS_ADDR_BITS 64
#if defined(CONFIG_USER_ONLY)
/* It looks like a lot of Linux programs assume page size
* is 4kB long. This is evil, but we have to deal with it...
#endif /* defined (TARGET_PPC64) */
-#include "cpu-defs.h"
+#define CPUState struct CPUPPCState
-#define REGX "%016" PRIx64
-#define ADDRX TARGET_FMT_lx
-#define PADDRX TARGET_FMT_plx
+#include "cpu-defs.h"
#include <setjmp.h>
/* Qemu exceptions: special cases we want to stop translation */
POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction */
POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */
+ POWERPC_EXCP_STCX = 0x204 /* Conditional stores in user mode */
};
/* Exceptions error codes */
/* SPR access micro-ops generations callbacks */
struct ppc_spr_t {
- void (*uea_read)(void *opaque, int spr_num);
- void (*uea_write)(void *opaque, int spr_num);
+ void (*uea_read)(void *opaque, int gpr_num, int spr_num);
+ void (*uea_write)(void *opaque, int spr_num, int gpr_num);
#if !defined(CONFIG_USER_ONLY)
- void (*oea_read)(void *opaque, int spr_num);
- void (*oea_write)(void *opaque, int spr_num);
- void (*hea_read)(void *opaque, int spr_num);
- void (*hea_write)(void *opaque, int spr_num);
+ void (*oea_read)(void *opaque, int gpr_num, int spr_num);
+ void (*oea_write)(void *opaque, int spr_num, int gpr_num);
+ void (*hea_read)(void *opaque, int gpr_num, int spr_num);
+ void (*hea_write)(void *opaque, int spr_num, int gpr_num);
#endif
const char *name;
};
/* Altivec registers (128 bits) */
union ppc_avr_t {
+ float32 f[4];
uint8_t u8[16];
uint16_t u16[8];
uint32_t u32[4];
+ int8_t s8[16];
+ int16_t s16[8];
+ int32_t s32[4];
uint64_t u64[2];
};
ppcemb_tlb_t tlbe;
};
+typedef struct ppc_slb_t ppc_slb_t;
+struct ppc_slb_t {
+ uint64_t tmp64;
+ uint32_t tmp;
+};
+
/*****************************************************************************/
/* Machine state register bits definition */
#define MSR_SF 63 /* Sixty-four-bit mode hflags */
#define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) & \
0x1F)
+/*****************************************************************************/
+/* Vector status and control register */
+#define VSCR_NJ 16 /* Vector non-java */
+#define VSCR_SAT 0 /* Vector saturation */
+#define vscr_nj (((env->vscr) >> VSCR_NJ) & 0x1)
+#define vscr_sat (((env->vscr) >> VSCR_SAT) & 0x1)
+
/*****************************************************************************/
/* The whole PowerPC CPU context */
#define NB_MMU_MODES 3
/* First are the most commonly used resources
* during translated code execution
*/
-#if TARGET_LONG_BITS > HOST_LONG_BITS
- target_ulong t0, t1;
-#endif
- /* XXX: this is a temporary workaround for i386. cf translate.c comment */
-#if (TARGET_LONG_BITS > HOST_LONG_BITS) || defined(HOST_I386)
- target_ulong t2;
-#endif
-
/* general purpose registers */
target_ulong gpr[32];
#if !defined(TARGET_PPC64)
/* XER */
target_ulong xer;
/* Reservation address */
- target_ulong reserve;
+ target_ulong reserve_addr;
+ /* Reservation value */
+ target_ulong reserve_val;
+ /* Reservation store address */
+ target_ulong reserve_ea;
+ /* Reserved store source register and size */
+ target_ulong reserve_info;
/* Those ones are used in supervisor mode only */
/* machine state register */
/* floating point status and control register */
uint32_t fpscr;
- CPU_COMMON
+ /* Next instruction pointer */
+ target_ulong nip;
int access_type; /* when a memory exception occurs, the access
type is stored here */
+ CPU_COMMON
+
/* MMU context - only relevant for full system emulation */
#if !defined(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64)
/* Address space register */
target_ulong asr;
/* PowerPC 64 SLB area */
+ ppc_slb_t slb[64];
int slb_nr;
#endif
/* segment registers */
target_ulong sdr1;
- target_ulong sr[16];
+ target_ulong sr[32];
/* BATs */
int nb_BATs;
target_ulong DBAT[2][8];
ppc_avr_t avr[32];
uint32_t vscr;
/* SPE registers */
- target_ulong spe_acc;
- float_status spe_status;
+ uint64_t spe_acc;
uint32_t spe_fscr;
+ /* SPE and Altivec can share a status since they will never be used
+ * simultaneously */
+ float_status vec_status;
/* Internal devices resources */
/* Time base and decrementer */
powerpc_input_t bus_model;
int bfd_mach;
uint32_t flags;
+ uint64_t insns_flags;
int error_code;
uint32_t pending_interrupts;
/* Exception vectors */
target_ulong excp_vectors[POWERPC_EXCP_NB];
target_ulong excp_prefix;
+ target_ulong hreset_excp_prefix;
target_ulong ivor_mask;
target_ulong ivpr_mask;
target_ulong hreset_vector;
#endif
/* Those resources are used only during code translation */
- /* Next instruction pointer */
- target_ulong nip;
-
/* opcode handlers */
opc_handler_t *opcodes[0x40];
typedef struct mmu_ctx_t mmu_ctx_t;
struct mmu_ctx_t {
target_phys_addr_t raddr; /* Real address */
+ target_phys_addr_t eaddr; /* Effective address */
int prot; /* Protection bits */
target_phys_addr_t pg_addr[2]; /* PTE tables base addresses */
target_ulong ptem; /* Virtual segment ID | API */
is returned if the signal was handled by the virtual CPU. */
int cpu_ppc_signal_handler (int host_signum, void *pinfo,
void *puc);
-
+int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
+ int mmu_idx, int is_softmmu);
+#define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
+int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong vaddr,
+ int rw, int access_type);
void do_interrupt (CPUPPCState *env);
void ppc_hw_interrupt (CPUPPCState *env);
-void cpu_loop_exit (void);
-void dump_stack (CPUPPCState *env);
+void cpu_dump_rfi (target_ulong RA, target_ulong msr);
#if !defined(CONFIG_USER_ONLY)
-target_ulong do_load_ibatu (CPUPPCState *env, int nr);
-target_ulong do_load_ibatl (CPUPPCState *env, int nr);
-void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value);
-void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value);
-target_ulong do_load_dbatu (CPUPPCState *env, int nr);
-target_ulong do_load_dbatl (CPUPPCState *env, int nr);
-void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
-void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
-void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value);
-void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value);
-target_ulong do_load_sdr1 (CPUPPCState *env);
-void do_store_sdr1 (CPUPPCState *env, target_ulong value);
+void ppc6xx_tlb_store (CPUPPCState *env, target_ulong EPN, int way, int is_code,
+ target_ulong pte0, target_ulong pte1);
+void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value);
+void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value);
+void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
+void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
+void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value);
+void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value);
+void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
#if defined(TARGET_PPC64)
-target_ulong ppc_load_asr (CPUPPCState *env);
void ppc_store_asr (CPUPPCState *env, target_ulong value);
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
-void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs);
+target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr);
+void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
#endif /* defined(TARGET_PPC64) */
-#if 0 // Unused
-target_ulong do_load_sr (CPUPPCState *env, int srnum);
-#endif
-void do_store_sr (CPUPPCState *env, int srnum, target_ulong value);
+void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
#endif /* !defined(CONFIG_USER_ONLY) */
void ppc_store_msr (CPUPPCState *env, target_ulong value);
-void cpu_ppc_reset (void *opaque);
-
void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
const ppc_def_t *cpu_ppc_find_by_name (const char *name);
#endif
#endif
-static always_inline uint64_t ppc_dump_gpr (CPUPPCState *env, int gprn)
+static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
{
uint64_t gprv;
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp);
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
-#define CPUState CPUPPCState
#define cpu_init cpu_ppc_init
#define cpu_exec cpu_ppc_exec
#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
#define cpu_list ppc_cpu_list
-#define CPU_SAVE_VERSION 3
+#define CPU_SAVE_VERSION 4
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _user
#if defined(CONFIG_USER_ONLY)
static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
{
- int i;
if (newsp)
env->gpr[1] = newsp;
- for (i = 7; i < 32; i++)
- env->gpr[i] = 0;
+ env->gpr[3] = 0;
}
#endif
#define SPR_604_HID15 (0x3FF)
#define SPR_E500_SVR (0x3FF)
+/*****************************************************************************/
+/* PowerPC Instructions types definitions */
+enum {
+ PPC_NONE = 0x0000000000000000ULL,
+ /* PowerPC base instructions set */
+ PPC_INSNS_BASE = 0x0000000000000001ULL,
+ /* integer operations instructions */
+#define PPC_INTEGER PPC_INSNS_BASE
+ /* flow control instructions */
+#define PPC_FLOW PPC_INSNS_BASE
+ /* virtual memory instructions */
+#define PPC_MEM PPC_INSNS_BASE
+ /* ld/st with reservation instructions */
+#define PPC_RES PPC_INSNS_BASE
+ /* spr/msr access instructions */
+#define PPC_MISC PPC_INSNS_BASE
+ /* Deprecated instruction sets */
+ /* Original POWER instruction set */
+ PPC_POWER = 0x0000000000000002ULL,
+ /* POWER2 instruction set extension */
+ PPC_POWER2 = 0x0000000000000004ULL,
+ /* Power RTC support */
+ PPC_POWER_RTC = 0x0000000000000008ULL,
+ /* Power-to-PowerPC bridge (601) */
+ PPC_POWER_BR = 0x0000000000000010ULL,
+ /* 64 bits PowerPC instruction set */
+ PPC_64B = 0x0000000000000020ULL,
+ /* New 64 bits extensions (PowerPC 2.0x) */
+ PPC_64BX = 0x0000000000000040ULL,
+ /* 64 bits hypervisor extensions */
+ PPC_64H = 0x0000000000000080ULL,
+ /* New wait instruction (PowerPC 2.0x) */
+ PPC_WAIT = 0x0000000000000100ULL,
+ /* Time base mftb instruction */
+ PPC_MFTB = 0x0000000000000200ULL,
+
+ /* Fixed-point unit extensions */
+ /* PowerPC 602 specific */
+ PPC_602_SPEC = 0x0000000000000400ULL,
+ /* isel instruction */
+ PPC_ISEL = 0x0000000000000800ULL,
+ /* popcntb instruction */
+ PPC_POPCNTB = 0x0000000000001000ULL,
+ /* string load / store */
+ PPC_STRING = 0x0000000000002000ULL,
+
+ /* Floating-point unit extensions */
+ /* Optional floating point instructions */
+ PPC_FLOAT = 0x0000000000010000ULL,
+ /* New floating-point extensions (PowerPC 2.0x) */
+ PPC_FLOAT_EXT = 0x0000000000020000ULL,
+ PPC_FLOAT_FSQRT = 0x0000000000040000ULL,
+ PPC_FLOAT_FRES = 0x0000000000080000ULL,
+ PPC_FLOAT_FRSQRTE = 0x0000000000100000ULL,
+ PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
+ PPC_FLOAT_FSEL = 0x0000000000400000ULL,
+ PPC_FLOAT_STFIWX = 0x0000000000800000ULL,
+
+ /* Vector/SIMD extensions */
+ /* Altivec support */
+ PPC_ALTIVEC = 0x0000000001000000ULL,
+ /* PowerPC 2.03 SPE extension */
+ PPC_SPE = 0x0000000002000000ULL,
+ /* PowerPC 2.03 SPE single-precision floating-point extension */
+ PPC_SPE_SINGLE = 0x0000000004000000ULL,
+ /* PowerPC 2.03 SPE double-precision floating-point extension */
+ PPC_SPE_DOUBLE = 0x0000000008000000ULL,
+
+ /* Optional memory control instructions */
+ PPC_MEM_TLBIA = 0x0000000010000000ULL,
+ PPC_MEM_TLBIE = 0x0000000020000000ULL,
+ PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
+ /* sync instruction */
+ PPC_MEM_SYNC = 0x0000000080000000ULL,
+ /* eieio instruction */
+ PPC_MEM_EIEIO = 0x0000000100000000ULL,
+
+ /* Cache control instructions */
+ PPC_CACHE = 0x0000000200000000ULL,
+ /* icbi instruction */
+ PPC_CACHE_ICBI = 0x0000000400000000ULL,
+ /* dcbz instruction with fixed cache line size */
+ PPC_CACHE_DCBZ = 0x0000000800000000ULL,
+ /* dcbz instruction with tunable cache line size */
+ PPC_CACHE_DCBZT = 0x0000001000000000ULL,
+ /* dcba instruction */
+ PPC_CACHE_DCBA = 0x0000002000000000ULL,
+ /* Freescale cache locking instructions */
+ PPC_CACHE_LOCK = 0x0000004000000000ULL,
+
+ /* MMU related extensions */
+ /* external control instructions */
+ PPC_EXTERN = 0x0000010000000000ULL,
+ /* segment register access instructions */
+ PPC_SEGMENT = 0x0000020000000000ULL,
+ /* PowerPC 6xx TLB management instructions */
+ PPC_6xx_TLB = 0x0000040000000000ULL,
+ /* PowerPC 74xx TLB management instructions */
+ PPC_74xx_TLB = 0x0000080000000000ULL,
+ /* PowerPC 40x TLB management instructions */
+ PPC_40x_TLB = 0x0000100000000000ULL,
+ /* segment register access instructions for PowerPC 64 "bridge" */
+ PPC_SEGMENT_64B = 0x0000200000000000ULL,
+ /* SLB management */
+ PPC_SLBI = 0x0000400000000000ULL,
+
+ /* Embedded PowerPC dedicated instructions */
+ PPC_WRTEE = 0x0001000000000000ULL,
+ /* PowerPC 40x exception model */
+ PPC_40x_EXCP = 0x0002000000000000ULL,
+ /* PowerPC 405 Mac instructions */
+ PPC_405_MAC = 0x0004000000000000ULL,
+ /* PowerPC 440 specific instructions */
+ PPC_440_SPEC = 0x0008000000000000ULL,
+ /* BookE (embedded) PowerPC specification */
+ PPC_BOOKE = 0x0010000000000000ULL,
+ /* mfapidi instruction */
+ PPC_MFAPIDI = 0x0020000000000000ULL,
+ /* tlbiva instruction */
+ PPC_TLBIVA = 0x0040000000000000ULL,
+ /* tlbivax instruction */
+ PPC_TLBIVAX = 0x0080000000000000ULL,
+ /* PowerPC 4xx dedicated instructions */
+ PPC_4xx_COMMON = 0x0100000000000000ULL,
+ /* PowerPC 40x ibct instructions */
+ PPC_40x_ICBT = 0x0200000000000000ULL,
+ /* rfmci is not implemented in all BookE PowerPC */
+ PPC_RFMCI = 0x0400000000000000ULL,
+ /* rfdi instruction */
+ PPC_RFDI = 0x0800000000000000ULL,
+ /* DCR accesses */
+ PPC_DCR = 0x1000000000000000ULL,
+ /* DCR extended accesse */
+ PPC_DCRX = 0x2000000000000000ULL,
+ /* user-mode DCR access, implemented in PowerPC 460 */
+ PPC_DCRUX = 0x4000000000000000ULL,
+};
+
/*****************************************************************************/
/* Memory access type :
* may be needed for precise access rights control and precise exceptions.
PPCBookE_INPUT_NB,
};
+enum {
+ /* PowerPC E500 input pins */
+ PPCE500_INPUT_RESET_CORE = 0,
+ PPCE500_INPUT_MCK = 1,
+ PPCE500_INPUT_CINT = 3,
+ PPCE500_INPUT_INT = 4,
+ PPCE500_INPUT_DEBUG = 6,
+ PPCE500_INPUT_NB,
+};
+
enum {
/* PowerPC 40x input pins */
PPC40x_INPUT_RESET_CORE = 0,
*flags = env->hflags;
}
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+#if defined(TARGET_PPC64)
+ /* The kernel checks TIF_32BIT here; we don't support loading 32-bit
+ binaries on PPC64 yet. */
+ env->gpr[13] = newtls;
+#else
+ env->gpr[2] = newtls;
+#endif
+}
+
#endif /* !defined (__CPU_PPC_H__) */