r3019 - in trunk/src/host/qemu-neo1973: . hw linux-user target-alpha target-ppc

andrew at sita.openmoko.org andrew at sita.openmoko.org
Thu Sep 20 15:33:25 CEST 2007


Author: andrew
Date: 2007-09-20 15:33:19 +0200 (Thu, 20 Sep 2007)
New Revision: 3019

Modified:
   trunk/src/host/qemu-neo1973/block-raw.c
   trunk/src/host/qemu-neo1973/cpu-defs.h
   trunk/src/host/qemu-neo1973/cpu-exec.c
   trunk/src/host/qemu-neo1973/exec-all.h
   trunk/src/host/qemu-neo1973/hw/cuda.c
   trunk/src/host/qemu-neo1973/hw/omap.c
   trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
   trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
   trunk/src/host/qemu-neo1973/monitor.c
   trunk/src/host/qemu-neo1973/target-alpha/cpu.h
   trunk/src/host/qemu-neo1973/target-ppc/cpu.h
   trunk/src/host/qemu-neo1973/target-ppc/helper.c
   trunk/src/host/qemu-neo1973/target-ppc/op.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
   trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h
   trunk/src/host/qemu-neo1973/target-ppc/translate.c
   trunk/src/host/qemu-neo1973/vl.h
Log:
Merge changes from upstream (closing bug #886).


Modified: trunk/src/host/qemu-neo1973/block-raw.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/block-raw.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -61,7 +61,8 @@
 
 #define DEBUG_BLOCK
 #if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
-#define DEBUG_BLOCK_PRINT(formatCstr, args...) fprintf(logfile, formatCstr, ##args); fflush(logfile)
+#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)	\
+    { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
 #else
 #define DEBUG_BLOCK_PRINT(formatCstr, args...)
 #endif
@@ -162,7 +163,7 @@
     if (ret == count)
         goto label__raw_read__success;
 
-    DEBUG_BLOCK_PRINT("raw_read(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
+    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
                       s->fd, bs->filename, offset, buf, count,
                       bs->total_sectors, ret, errno, strerror(errno));
 
@@ -177,13 +178,11 @@
         if (ret == count)
             goto label__raw_read__success;
 
-        DEBUG_BLOCK_PRINT("raw_read(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
+        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
                           s->fd, bs->filename, offset, buf, count,
                           bs->total_sectors, ret, errno, strerror(errno));
     }
 
-    return -1;
-
 label__raw_read__success:
 
     return ret;
@@ -202,7 +201,7 @@
     if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
         ++(s->lseek_err_cnt);
         if(s->lseek_err_cnt) {
-            DEBUG_BLOCK_PRINT("raw_write(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
+            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
                               s->fd, bs->filename, offset, buf, count,
                               bs->total_sectors, errno, strerror(errno));
         }
@@ -214,12 +213,10 @@
     if (ret == count)
         goto label__raw_write__success;
 
-    DEBUG_BLOCK_PRINT("raw_write(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
+    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
                       s->fd, bs->filename, offset, buf, count,
                       bs->total_sectors, ret, errno, strerror(errno));
 
-    return -1;
-
 label__raw_write__success:
 
     return ret;

Modified: trunk/src/host/qemu-neo1973/cpu-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-defs.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/cpu-defs.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -45,11 +45,13 @@
 typedef uint32_t target_ulong;
 #define TARGET_FMT_lx "%08x"
 #define TARGET_FMT_ld "%d"
+#define TARGET_FMT_lu "%u"
 #elif TARGET_LONG_SIZE == 8
 typedef int64_t target_long;
 typedef uint64_t target_ulong;
 #define TARGET_FMT_lx "%016" PRIx64
 #define TARGET_FMT_ld "%" PRId64
+#define TARGET_FMT_lu "%" PRIu64
 #else
 #error TARGET_LONG_SIZE undefined
 #endif

Modified: trunk/src/host/qemu-neo1973/cpu-exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-exec.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/cpu-exec.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -187,8 +187,7 @@
     cs_base = env->npc;
     pc = env->pc;
 #elif defined(TARGET_PPC)
-    flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
-        (msr_se << MSR_SE) | (msr_le << MSR_LE);
+    flags = env->hflags;
     cs_base = 0;
     pc = env->nip;
 #elif defined(TARGET_MIPS)

Modified: trunk/src/host/qemu-neo1973/exec-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/exec-all.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/exec-all.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -28,10 +28,15 @@
 #define tostring(s)	#s
 #endif
 
+#ifndef likely
 #if __GNUC__ < 3
 #define __builtin_expect(x, n) (x)
 #endif
 
+#define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x)   __builtin_expect(!!(x), 0)
+#endif
+
 #ifdef __i386__
 #define REGPARM(n) __attribute((regparm(n)))
 #else

Modified: trunk/src/host/qemu-neo1973/hw/cuda.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cuda.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/hw/cuda.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -557,6 +557,12 @@
         cuda_send_packet_to_host(s, obuf, 2);
 	qemu_system_shutdown_request();
 	break;
+    case CUDA_RESET_SYSTEM:
+        obuf[0] = CUDA_PACKET;
+        obuf[1] = 0;
+        cuda_send_packet_to_host(s, obuf, 2);
+        qemu_system_reset_request();
+        break;
     default:
         break;
     }

Modified: trunk/src/host/qemu-neo1973/hw/omap.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/hw/omap.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -46,9 +46,6 @@
     OMAP_32B_REG(addr);
 }
 
-#define likely
-#define unlikely
-
 /* Interrupt Handlers */
 struct omap_intr_handler_s {
     qemu_irq *pins;

Modified: trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -75,7 +75,10 @@
     int i, n;
 
     /* We put the bd structure at the top of memory */
-    bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
+    if (bd->bi_memsize >= 0x01000000UL)
+        bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
+    else
+        bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
     stl_raw(phys_ram_base + bdloc + 0x00, bd->bi_memstart);
     stl_raw(phys_ram_base + bdloc + 0x04, bd->bi_memsize);
     stl_raw(phys_ram_base + bdloc + 0x08, bd->bi_flashstart);
@@ -952,7 +955,8 @@
         bcr = 0x000C0000;
         break;
     default:
-        printf("%s: invalid RAM size " TARGET_FMT_ld "\n", __func__, ram_size);
+        printf("%s: invalid RAM size " TARGET_FMT_plx "\n",
+               __func__, ram_size);
         return 0x00000000;
     }
     bcr |= ram_base & 0xFF800000;
@@ -985,8 +989,8 @@
     if (*bcrp & 0x00000001) {
         /* Unmap RAM */
 #ifdef DEBUG_SDRAM
-        printf("%s: unmap RAM area " ADDRX " " ADDRX "\n", __func__,
-               sdram_base(*bcrp), sdram_size(*bcrp));
+        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
 #endif
         cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
                                      IO_MEM_UNASSIGNED);
@@ -994,8 +998,8 @@
     *bcrp = bcr & 0xFFDEE001;
     if (enabled && (bcr & 0x00000001)) {
 #ifdef DEBUG_SDRAM
-        printf("%s: Map RAM area " ADDRX " " ADDRX "\n", __func__,
-               sdram_base(bcr), sdram_size(bcr));
+        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
 #endif
         cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
                                      sdram_base(bcr) | IO_MEM_RAM);
@@ -1023,8 +1027,8 @@
 
     for (i = 0; i < sdram->nbanks; i++) {
 #ifdef DEBUG_SDRAM
-        printf("%s: Unmap RAM area " ADDRX " " ADDRX "\n", __func__,
-               sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
 #endif
         cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
                                      sdram_size(sdram->bcr[i]),

Modified: trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -865,9 +865,14 @@
 #define TARGET_MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define TARGET_MAP_DENYWRITE	0x0800		/* ETXTBSY */
 #define TARGET_MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#if defined(TARGET_PPC)
+#define TARGET_MAP_LOCKED	0x0080		/* pages are locked */
+#define TARGET_MAP_NORESERVE	0x0040		/* don't check for reservations */
+#else
 #define TARGET_MAP_LOCKED	0x2000		/* pages are locked */
 #define TARGET_MAP_NORESERVE	0x4000		/* don't check for reservations */
 #endif
+#endif
 
 #if defined(TARGET_I386) || defined(TARGET_ARM)
 struct target_stat {

Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/monitor.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -1442,21 +1442,7 @@
     CPUState *env = mon_get_cpu();
     if (!env)
         return 0;
-    return (env->msr[MSR_POW] << MSR_POW) |
-        (env->msr[MSR_ILE] << MSR_ILE) |
-        (env->msr[MSR_EE] << MSR_EE) |
-        (env->msr[MSR_PR] << MSR_PR) |
-        (env->msr[MSR_FP] << MSR_FP) |
-        (env->msr[MSR_ME] << MSR_ME) |
-        (env->msr[MSR_FE0] << MSR_FE0) |
-        (env->msr[MSR_SE] << MSR_SE) |
-        (env->msr[MSR_BE] << MSR_BE) |
-        (env->msr[MSR_FE1] << MSR_FE1) |
-        (env->msr[MSR_IP] << MSR_IP) |
-        (env->msr[MSR_IR] << MSR_IR) |
-        (env->msr[MSR_DR] << MSR_DR) |
-        (env->msr[MSR_RI] << MSR_RI) |
-        (env->msr[MSR_LE] << MSR_LE);
+    return do_load_msr(env);
 }
 
 static target_long monitor_get_xer (struct MonitorDef *md, int val)
@@ -1464,10 +1450,7 @@
     CPUState *env = mon_get_cpu();
     if (!env)
         return 0;
-    return (env->xer[XER_SO] << XER_SO) |
-        (env->xer[XER_OV] << XER_OV) |
-        (env->xer[XER_CA] << XER_CA) |
-        (env->xer[XER_BC] << XER_BC);
+    return ppc_load_xer(env);
 }
 
 static target_long monitor_get_decr (struct MonitorDef *md, int val)
@@ -1551,6 +1534,7 @@
     SEG("gs", R_GS)
     { "pc", 0, monitor_get_pc, },
 #elif defined(TARGET_PPC)
+    /* General purpose registers */
     { "r0", offsetof(CPUState, gpr[0]) },
     { "r1", offsetof(CPUState, gpr[1]) },
     { "r2", offsetof(CPUState, gpr[2]) },
@@ -1583,15 +1567,56 @@
     { "r29", offsetof(CPUState, gpr[29]) },
     { "r30", offsetof(CPUState, gpr[30]) },
     { "r31", offsetof(CPUState, gpr[31]) },
+    /* Floating point registers */
+    { "f0", offsetof(CPUState, fpr[0]) },
+    { "f1", offsetof(CPUState, fpr[1]) },
+    { "f2", offsetof(CPUState, fpr[2]) },
+    { "f3", offsetof(CPUState, fpr[3]) },
+    { "f4", offsetof(CPUState, fpr[4]) },
+    { "f5", offsetof(CPUState, fpr[5]) },
+    { "f6", offsetof(CPUState, fpr[6]) },
+    { "f7", offsetof(CPUState, fpr[7]) },
+    { "f8", offsetof(CPUState, fpr[8]) },
+    { "f9", offsetof(CPUState, fpr[9]) },
+    { "f10", offsetof(CPUState, fpr[10]) },
+    { "f11", offsetof(CPUState, fpr[11]) },
+    { "f12", offsetof(CPUState, fpr[12]) },
+    { "f13", offsetof(CPUState, fpr[13]) },
+    { "f14", offsetof(CPUState, fpr[14]) },
+    { "f15", offsetof(CPUState, fpr[15]) },
+    { "f16", offsetof(CPUState, fpr[16]) },
+    { "f17", offsetof(CPUState, fpr[17]) },
+    { "f18", offsetof(CPUState, fpr[18]) },
+    { "f19", offsetof(CPUState, fpr[19]) },
+    { "f20", offsetof(CPUState, fpr[20]) },
+    { "f21", offsetof(CPUState, fpr[21]) },
+    { "f22", offsetof(CPUState, fpr[22]) },
+    { "f23", offsetof(CPUState, fpr[23]) },
+    { "f24", offsetof(CPUState, fpr[24]) },
+    { "f25", offsetof(CPUState, fpr[25]) },
+    { "f26", offsetof(CPUState, fpr[26]) },
+    { "f27", offsetof(CPUState, fpr[27]) },
+    { "f28", offsetof(CPUState, fpr[28]) },
+    { "f29", offsetof(CPUState, fpr[29]) },
+    { "f30", offsetof(CPUState, fpr[30]) },
+    { "f31", offsetof(CPUState, fpr[31]) },
+    { "fpscr", offsetof(CPUState, fpscr) },
+    /* Next instruction pointer */
     { "nip|pc", offsetof(CPUState, nip) },
     { "lr", offsetof(CPUState, lr) },
     { "ctr", offsetof(CPUState, ctr) },
     { "decr", 0, &monitor_get_decr, },
     { "ccr", 0, &monitor_get_ccr, },
+    /* Machine state register */
     { "msr", 0, &monitor_get_msr, },
     { "xer", 0, &monitor_get_xer, },
     { "tbu", 0, &monitor_get_tbu, },
     { "tbl", 0, &monitor_get_tbl, },
+#if defined(TARGET_PPC64)
+    /* Address space register */
+    { "asr", offsetof(CPUState, asr) },
+#endif
+    /* Segment registers */
     { "sdr1", offsetof(CPUState, sdr1) },
     { "sr0", offsetof(CPUState, sr[0]) },
     { "sr1", offsetof(CPUState, sr[1]) },

Modified: trunk/src/host/qemu-neo1973/target-alpha/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/cpu.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-alpha/cpu.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -32,10 +32,6 @@
 
 #include "softfloat.h"
 
-/* XXX: put this in a common place */
-#define likely(x)   __builtin_expect(!!(x), 1)
-#define unlikely(x)   __builtin_expect(!!(x), 0)
-
 #define TARGET_HAS_ICE 1
 
 #define ELF_MACHINE	EM_ALPHA

Modified: trunk/src/host/qemu-neo1973/target-ppc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/cpu.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/cpu.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -23,36 +23,45 @@
 #include "config.h"
 #include <inttypes.h>
 
-#if !defined(TARGET_PPCEMB)
-#if defined(TARGET_PPC64) || (HOST_LONG_BITS >= 64)
-/* When using 64 bits temporary registers,
- * we can use 64 bits GPR with no extra cost
- */
-#define TARGET_PPCEMB
-#endif
-#endif
-
 #if defined (TARGET_PPC64)
 typedef uint64_t ppc_gpr_t;
+#define TARGET_GPR_BITS  64
 #define TARGET_LONG_BITS 64
-#define TARGET_GPR_BITS  64
 #define REGX "%016" PRIx64
 #define TARGET_PAGE_BITS 12
 #elif defined(TARGET_PPCEMB)
-/* e500v2 have 36 bits physical address space */
+/* BookE have 36 bits physical address space */
 #define TARGET_PHYS_ADDR_BITS 64
 /* GPR are 64 bits: used by vector extension */
 typedef uint64_t ppc_gpr_t;
+#define TARGET_GPR_BITS  64
 #define TARGET_LONG_BITS 32
-#define TARGET_GPR_BITS  64
 #define REGX "%016" PRIx64
+#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...
+ */
+#define TARGET_PAGE_BITS 12
+#else
 /* Pages can be 1 kB small */
 #define TARGET_PAGE_BITS 10
+#endif
 #else
+#if (HOST_LONG_BITS >= 64)
+/* When using 64 bits temporary registers,
+ * we can use 64 bits GPR with no extra cost
+ * It's even an optimization as it will prevent
+ * the compiler to do unuseful masking in the micro-ops.
+ */
+typedef uint64_t ppc_gpr_t;
+#define TARGET_GPR_BITS  64
+#define REGX "%08" PRIx64
+#else
 typedef uint32_t ppc_gpr_t;
-#define TARGET_LONG_BITS 32
 #define TARGET_GPR_BITS  32
 #define REGX "%08" PRIx32
+#endif
+#define TARGET_LONG_BITS 32
 #define TARGET_PAGE_BITS 12
 #endif
 
@@ -79,10 +88,6 @@
 #define ICACHE_LINE_SIZE 32
 #define DCACHE_LINE_SIZE 32
 
-/* XXX: put this in a common place */
-#define likely(x)   __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-
 /*****************************************************************************/
 /* PVR definitions for most known PowerPC */
 enum {
@@ -380,19 +385,19 @@
     PPC_64_BRIDGE   = 0x0000000004000000ULL,
     /* BookE (embedded) PowerPC specification      */
     PPC_BOOKE       = 0x0000000008000000ULL,
-    /* eieio */
+    /* eieio                                       */
     PPC_MEM_EIEIO   = 0x0000000010000000ULL,
-    /* e500 vector instructions */
+    /* e500 vector instructions                    */
     PPC_E500_VECTOR = 0x0000000020000000ULL,
-    /* PowerPC 4xx dedicated instructions     */
+    /* PowerPC 4xx dedicated instructions          */
     PPC_4xx_COMMON  = 0x0000000040000000ULL,
-    /* PowerPC 2.03 specification extensions */
+    /* PowerPC 2.03 specification extensions       */
     PPC_203         = 0x0000000080000000ULL,
-    /* PowerPC 2.03 SPE extension */
+    /* PowerPC 2.03 SPE extension                  */
     PPC_SPE         = 0x0000000100000000ULL,
-    /* PowerPC 2.03 SPE floating-point extension */
+    /* PowerPC 2.03 SPE floating-point extension   */
     PPC_SPEFPU      = 0x0000000200000000ULL,
-    /* SLB management */
+    /* SLB management                              */
     PPC_SLBI        = 0x0000000400000000ULL,
 };
 
@@ -909,8 +914,6 @@
 
 /*****************************************************************************/
 /* Registers definitions */
-#define ugpr(n) (env->gpr[n])
-
 #define XER_SO 31
 #define XER_OV 30
 #define XER_CA 29
@@ -1307,7 +1310,6 @@
                                    /* may change privilege level             */
 #define EXCP_BRANCH        0x11001 /* branch instruction                     */
 #define EXCP_SYSCALL_USER  0x12000 /* System call in user mode only          */
-#define EXCP_INTERRUPT_CRITICAL 0x13000 /* critical IRQ                      */
 
 /* Error codes */
 enum {
@@ -1342,8 +1344,8 @@
     EXCP_INVAL_FP      = 0x04,  /* Unimplemented mandatory fp instr */
     /* Privileged instruction */
     EXCP_PRIV          = 0x30,
-    EXCP_PRIV_OPC      = 0x01,
-    EXCP_PRIV_REG      = 0x02,
+    EXCP_PRIV_OPC      = 0x01,  /* Privileged operation exception   */
+    EXCP_PRIV_REG      = 0x02,  /* Privileged register exception    */
     /* Trap */
     EXCP_TRAP          = 0x40,
 };

Modified: trunk/src/host/qemu-neo1973/target-ppc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -77,24 +77,62 @@
     *pte0 &= ~0x80000000;
 }
 
+#if defined(TARGET_PPC64)
+static inline int pte64_is_valid (target_ulong pte0)
+{
+    return pte0 & 0x0000000000000001ULL ? 1 : 0;
+}
+
+static inline void pte64_invalidate (target_ulong *pte0)
+{
+    *pte0 &= ~0x0000000000000001ULL;
+}
+#endif
+
 #define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
+#if defined(TARGET_PPC64)
+#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
+#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
+#endif
 
-static int pte_check (mmu_ctx_t *ctx,
-                      target_ulong pte0, target_ulong pte1, int h, int rw)
+static inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
+                              target_ulong pte0, target_ulong pte1,
+                              int h, int rw)
 {
-    int access, ret;
+    target_ulong ptem, mmask;
+    int access, ret, pteh, ptev;
 
     access = 0;
     ret = -1;
     /* Check validity and table match */
-    if (pte_is_valid(pte0) && (h == ((pte0 >> 6) & 1))) {
+#if defined(TARGET_PPC64)
+    if (is_64b) {
+        ptev = pte64_is_valid(pte0);
+        pteh = (pte0 >> 1) & 1;
+    } else
+#endif
+    {
+        ptev = pte_is_valid(pte0);
+        pteh = (pte0 >> 6) & 1;
+    }
+    if (ptev && h == pteh) {
         /* Check vsid & api */
-        if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
+#if defined(TARGET_PPC64)
+        if (is_64b) {
+            ptem = pte0 & PTE64_PTEM_MASK;
+            mmask = PTE64_CHECK_MASK;
+        } else
+#endif
+        {
+            ptem = pte0 & PTE_PTEM_MASK;
+            mmask = PTE_CHECK_MASK;
+        }
+        if (ptem == ctx->ptem) {
             if (ctx->raddr != (target_ulong)-1) {
                 /* all matches should have equal RPN, WIMG & PP */
-                if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
-                    if (loglevel > 0)
+                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
+                    if (loglevel != 0)
                         fprintf(logfile, "Bad RPN/WIMG/PP\n");
                     return -3;
                 }
@@ -143,6 +181,20 @@
     return ret;
 }
 
+static int pte32_check (mmu_ctx_t *ctx,
+                        target_ulong pte0, target_ulong pte1, int h, int rw)
+{
+    return _pte_check(ctx, 0, pte0, pte1, h, rw);
+}
+
+#if defined(TARGET_PPC64)
+static int pte64_check (mmu_ctx_t *ctx,
+                        target_ulong pte0, target_ulong pte1, int h, int rw)
+{
+    return _pte_check(ctx, 1, pte0, pte1, h, rw);
+}
+#endif
+
 static int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
                              int ret, int rw)
 {
@@ -305,7 +357,7 @@
                     rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
         }
 #endif
-        switch (pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
+        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
         case -3:
             /* TLB inconsistency */
             return -1;
@@ -440,26 +492,36 @@
 }
 
 /* PTE table lookup */
-static int find_pte (mmu_ctx_t *ctx, int h, int rw)
+static inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h, int rw)
 {
     target_ulong base, pte0, pte1;
     int i, good = -1;
-    int ret;
+    int ret, r;
 
     ret = -1; /* No entry found */
     base = ctx->pg_addr[h];
     for (i = 0; i < 8; i++) {
-        pte0 = ldl_phys(base + (i * 8));
-        pte1 =  ldl_phys(base + (i * 8) + 4);
+#if defined(TARGET_PPC64)
+        if (is_64b) {
+            pte0 = ldq_phys(base + (i * 16));
+            pte1 =  ldq_phys(base + (i * 16) + 8);
+            r = pte64_check(ctx, pte0, pte1, h, rw);
+        } else
+#endif
+        {
+            pte0 = ldl_phys(base + (i * 8));
+            pte1 =  ldl_phys(base + (i * 8) + 4);
+            r = pte32_check(ctx, pte0, pte1, h, rw);
+        }
 #if defined (DEBUG_MMU)
-        if (loglevel > 0) {
+        if (loglevel != 0) {
             fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
                     " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
                     base + (i * 8), pte0, pte1,
-                    pte0 >> 31, h, (pte0 >> 6) & 1, ctx->ptem);
+                    (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1), ctx->ptem);
         }
 #endif
-        switch (pte_check(ctx, pte0, pte1, h, rw)) {
+        switch (r) {
         case -3:
             /* PTE inconsistency */
             return -1;
@@ -494,59 +556,183 @@
 #endif
         /* Update page flags */
         pte1 = ctx->raddr;
-        if (pte_update_flags(ctx, &pte1, ret, rw) == 1)
-            stl_phys_notdirty(base + (good * 8) + 4, pte1);
+        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+#if defined(TARGET_PPC64)
+            if (is_64b) {
+                stq_phys_notdirty(base + (good * 16) + 8, pte1);
+            } else
+#endif
+            {
+                stl_phys_notdirty(base + (good * 8) + 4, pte1);
+            }
+        }
     }
 
     return ret;
 }
 
+static int find_pte32 (mmu_ctx_t *ctx, int h, int rw)
+{
+    return _find_pte(ctx, 0, h, rw);
+}
+
+#if defined(TARGET_PPC64)
+static int find_pte64 (mmu_ctx_t *ctx, int h, int rw)
+{
+    return _find_pte(ctx, 1, h, rw);
+}
+#endif
+
+static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw)
+{
+#if defined(TARGET_PPC64)
+    if (PPC_MMU(env) == PPC_FLAGS_MMU_64B ||
+        PPC_MMU(env) == PPC_FLAGS_MMU_64BRIDGE)
+        return find_pte64(ctx, h, rw);
+#endif
+
+    return find_pte32(ctx, h, rw);
+}
+
 static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
+                                             int sdr_sh,
                                              target_phys_addr_t hash,
                                              target_phys_addr_t mask)
 {
-    return (sdr1 & 0xFFFF0000) | (hash & mask);
+    return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
 }
 
+#if defined(TARGET_PPC64)
+static int slb_lookup (CPUState *env, target_ulong eaddr,
+                       target_ulong *vsid, target_ulong *page_mask, int *attr)
+{
+    target_phys_addr_t sr_base;
+    target_ulong mask;
+    uint64_t tmp64;
+    uint32_t tmp;
+    int n, ret;
+    int slb_nr;
+
+    ret = -5;
+    sr_base = env->spr[SPR_ASR];
+    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
+#if 0 /* XXX: Fix this */
+    slb_nr = env->slb_nr;
+#else
+    slb_nr = 32;
+#endif
+    for (n = 0; n < slb_nr; n++) {
+        tmp64 = ldq_phys(sr_base);
+        if (tmp64 & 0x0000000008000000ULL) {
+            /* SLB entry is valid */
+            switch (tmp64 & 0x0000000006000000ULL) {
+            case 0x0000000000000000ULL:
+                /* 256 MB segment */
+                mask = 0xFFFFFFFFF0000000ULL;
+                break;
+            case 0x0000000002000000ULL:
+                /* 1 TB segment */
+                mask = 0xFFFF000000000000ULL;
+                break;
+            case 0x0000000004000000ULL:
+            case 0x0000000006000000ULL:
+                /* Reserved => segment is invalid */
+                continue;
+            }
+            if ((eaddr & mask) == (tmp64 & mask)) {
+                /* SLB match */
+                tmp = ldl_phys(sr_base + 8);
+                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
+                *page_mask = ~mask;
+                *attr = tmp & 0xFF;
+                ret = 0;
+                break;
+            }
+        }
+        sr_base += 12;
+    }
+
+    return ret;
+}
+#endif /* defined(TARGET_PPC64) */
+
 /* Perform segment based translation */
 static int get_segment (CPUState *env, mmu_ctx_t *ctx,
                         target_ulong eaddr, int rw, int type)
 {
-    target_phys_addr_t sdr, hash, mask;
-    target_ulong sr, vsid, pgidx;
-    int ret = -1, ret2;
+    target_phys_addr_t sdr, hash, mask, sdr_mask;
+    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
+#if defined(TARGET_PPC64)
+    int attr;
+#endif
+    int ds, nx, vsid_sh, sdr_sh;
+    int ret, ret2;
 
-    sr = env->sr[eaddr >> 28];
+#if defined(TARGET_PPC64)
+    if (PPC_MMU(env) == PPC_FLAGS_MMU_64B) {
+        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
+        if (ret < 0)
+            return ret;
+        ctx->key = ((attr & 0x40) && msr_pr == 1) ||
+            ((attr & 0x80) && msr_pr == 0) ? 1 : 0;
+        ds = 0;
+        nx = attr & 0x20 ? 1 : 0;
+        vsid_mask = 0x00003FFFFFFFFF80ULL;
+        vsid_sh = 7;
+        sdr_sh = 18;
+        sdr_mask = 0x3FF80;
+    } else
+#endif /* defined(TARGET_PPC64) */
+    {
+        sr = env->sr[eaddr >> 28];
+        page_mask = 0x0FFFFFFF;
+        ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
+                    ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
+        ds = sr & 0x80000000 ? 1 : 0;
+        nx = sr & 0x10000000 ? 1 : 0;
+        vsid = sr & 0x00FFFFFF;
+        vsid_mask = 0x01FFFFC0;
+        vsid_sh = 6;
+        sdr_sh = 16;
+        sdr_mask = 0xFFC0;
 #if defined (DEBUG_MMU)
-    if (loglevel > 0) {
-        fprintf(logfile, "Check segment v=0x" ADDRX " %d 0x" ADDRX " nip=0x"
-                ADDRX " lr=0x" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
-                eaddr, eaddr >> 28, sr, env->nip,
-                env->lr, msr_ir, msr_dr, msr_pr, rw, type);
-    }
-#endif
-    ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
-                ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
-    if ((sr & 0x80000000) == 0) {
-#if defined (DEBUG_MMU)
-        if (loglevel > 0)
+        if (loglevel != 0) {
+            fprintf(logfile, "Check segment v=0x" ADDRX " %d 0x" ADDRX
+                    " nip=0x" ADDRX " lr=0x" ADDRX
+                    " ir=%d dr=%d pr=%d %d t=%d\n",
+                    eaddr, (int)(eaddr >> 28), sr, env->nip,
+                    env->lr, msr_ir, msr_dr, msr_pr, rw, type);
+        }
+        if (!ds && loglevel != 0) {
             fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n",
                     ctx->key, sr & 0x10000000);
+        }
 #endif
+    }
+    ret = -1;
+    if (!ds) {
         /* Check if instruction fetch is allowed, if needed */
-        if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
+        if (type != ACCESS_CODE || nx == 0) {
             /* Page address translation */
-            pgidx = (eaddr >> TARGET_PAGE_BITS) & 0xFFFF;
-            vsid = sr & 0x00FFFFFF;
-            hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
+            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
+            hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
             /* Primary table address */
             sdr = env->sdr1;
-            mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
-            ctx->pg_addr[0] = get_pgaddr(sdr, hash, mask);
+            mask = ((sdr & 0x000001FF) << sdr_sh) | sdr_mask;
+            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
             /* Secondary table address */
-            hash = (~hash) & 0x01FFFFC0;
-            ctx->pg_addr[1] = get_pgaddr(sdr, hash, mask);
-            ctx->ptem = (vsid << 7) | (pgidx >> 10);
+            hash = (~hash) & vsid_mask;
+            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
+#if defined(TARGET_PPC64)
+            if (PPC_MMU(env) == PPC_FLAGS_MMU_64B ||
+                PPC_MMU(env) == PPC_FLAGS_MMU_64BRIDGE) {
+                /* Only 5 bits of the page index are used in the AVPN */
+                ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
+            } else
+#endif
+            {
+                ctx->ptem = (vsid << 7) | (pgidx >> 10);
+            }
             /* Initialize real address with an invalid value */
             ctx->raddr = (target_ulong)-1;
             if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
@@ -562,7 +748,7 @@
                 }
 #endif
                 /* Primary table lookup */
-                ret = find_pte(ctx, 0, rw);
+                ret = find_pte(env, ctx, 0, rw);
                 if (ret < 0) {
                     /* Secondary table lookup */
 #if defined (DEBUG_MMU)
@@ -574,7 +760,7 @@
                                 (uint32_t)hash, ctx->pg_addr[1]);
                     }
 #endif
-                    ret2 = find_pte(ctx, 1, rw);
+                    ret2 = find_pte(env, ctx, 1, rw);
                     if (ret2 != -1)
                         ret = ret2;
                 }
@@ -827,6 +1013,52 @@
     env->spr[SPR_405_SLER] = val;
 }
 
+int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
+                                   target_ulong address, int rw,
+                                   int access_type)
+{
+    ppcemb_tlb_t *tlb;
+    target_phys_addr_t raddr;
+    int i, prot, ret;
+
+    ret = -1;
+    raddr = -1;
+    for (i = 0; i < env->nb_tlb; i++) {
+        tlb = &env->tlb[i].tlbe;
+        if (ppcemb_tlb_check(env, tlb, &raddr, address,
+                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
+            continue;
+        if (msr_pr)
+            prot = tlb->prot & 0xF;
+        else
+            prot = (tlb->prot >> 4) & 0xF;
+        /* Check the address space */
+        if (access_type == ACCESS_CODE) {
+            if (msr_is != (tlb->attr & 1))
+                continue;
+            ctx->prot = prot;
+            if (prot & PAGE_EXEC) {
+                ret = 0;
+                break;
+            }
+            ret = -3;
+        } else {
+            if (msr_ds != (tlb->attr & 1))
+                continue;
+            ctx->prot = prot;
+            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
+                ret = 0;
+                break;
+            }
+            ret = -2;
+        }
+    }
+    if (ret >= 0)
+        ctx->raddr = raddr;
+
+    return ret;
+}
+
 static int check_physical (CPUState *env, mmu_ctx_t *ctx,
                            target_ulong eaddr, int rw)
 {
@@ -835,29 +1067,54 @@
     ctx->raddr = eaddr;
     ctx->prot = PAGE_READ;
     ret = 0;
-    if (unlikely(msr_pe != 0 && PPC_MMU(env) == PPC_FLAGS_MMU_403)) {
-        /* 403 family add some particular protections,
-         * using PBL/PBU registers for accesses with no translation.
-         */
-        in_plb =
-            /* Check PLB validity */
-            (env->pb[0] < env->pb[1] &&
-             /* and address in plb area */
-             eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
-            (env->pb[2] < env->pb[3] &&
-             eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
-        if (in_plb ^ msr_px) {
-            /* Access in protected area */
-            if (rw == 1) {
-                /* Access is not allowed */
-                ret = -2;
+    switch (PPC_MMU(env)) {
+    case PPC_FLAGS_MMU_32B:
+    case PPC_FLAGS_MMU_SOFT_6xx:
+    case PPC_FLAGS_MMU_601:
+    case PPC_FLAGS_MMU_SOFT_4xx:
+        ctx->prot |= PAGE_WRITE;
+        break;
+#if defined(TARGET_PPC64)
+    case PPC_FLAGS_MMU_64B:
+    case PPC_FLAGS_MMU_64BRIDGE:
+#endif
+        /* Real address are 60 bits long */
+        ctx->raddr &= 0x0FFFFFFFFFFFFFFFUL;
+        ctx->prot |= PAGE_WRITE;
+        break;
+    case PPC_FLAGS_MMU_403:
+        if (unlikely(msr_pe != 0)) {
+            /* 403 family add some particular protections,
+             * using PBL/PBU registers for accesses with no translation.
+             */
+            in_plb =
+                /* Check PLB validity */
+                (env->pb[0] < env->pb[1] &&
+                 /* and address in plb area */
+                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
+                (env->pb[2] < env->pb[3] &&
+                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
+            if (in_plb ^ msr_px) {
+                /* Access in protected area */
+                if (rw == 1) {
+                    /* Access is not allowed */
+                    ret = -2;
+                }
+            } else {
+                /* Read-write access is allowed */
+                ctx->prot |= PAGE_WRITE;
             }
-        } else {
-            /* Read-write access is allowed */
-            ctx->prot |= PAGE_WRITE;
         }
-    } else {
+    case PPC_FLAGS_MMU_BOOKE:
         ctx->prot |= PAGE_WRITE;
+        break;
+    case PPC_FLAGS_MMU_BOOKE_FSL:
+        /* XXX: TODO */
+        cpu_abort(env, "BookE FSL MMU model not implemented\n");
+        break;
+    default:
+        cpu_abort(env, "Unknown or invalid MMU model\n");
+        return -1;
     }
 
     return ret;
@@ -904,9 +1161,9 @@
             cpu_abort(env, "601 MMU model not implemented\n");
             return -1;
         case PPC_FLAGS_MMU_BOOKE:
-            /* XXX: TODO */
-            cpu_abort(env, "BookeE MMU model not implemented\n");
-            return -1;
+            ret = mmubooke_get_physical_address(env, ctx, eaddr,
+                                                rw, access_type);
+            break;
         case PPC_FLAGS_MMU_BOOKE_FSL:
             /* XXX: TODO */
             cpu_abort(env, "BookE FSL MMU model not implemented\n");
@@ -1739,7 +1996,7 @@
         cpu_abort(env, "Floating point assist exception "
                   "is not implemented yet !\n");
         goto store_next;
-        /* 64 bits PowerPC exceptions */
+    /* 64 bits PowerPC exceptions */
     case EXCP_DSEG: /* 0x0380 */
         /* XXX: TODO */
         cpu_abort(env, "Data segment exception is not implemented yet !\n");
@@ -2235,28 +2492,39 @@
 void cpu_ppc_reset (void *opaque)
 {
     CPUPPCState *env;
+    int i;
 
     env = opaque;
+    /* XXX: some of those flags initialisation values could depend
+     *      on the actual PowerPC implementation
+     */
+    for (i = 0; i < 63; i++)
+        env->msr[i] = 0;
+#if defined(TARGET_PPC64)
+    msr_hv = 0; /* Should be 1... */
+#endif
+    msr_ap = 0; /* TO BE CHECKED */
+    msr_sa = 0; /* TO BE CHECKED */
+    msr_ip = 0; /* TO BE CHECKED */
 #if defined (DO_SINGLE_STEP) && 0
     /* Single step trace mode */
     msr_se = 1;
     msr_be = 1;
 #endif
+#if defined(CONFIG_USER_ONLY)
     msr_fp = 1; /* Allow floating point exceptions */
-    msr_me = 1; /* Allow machine check exceptions  */
-#if defined(TARGET_PPC64)
-    msr_sf = 0; /* Boot in 32 bits mode */
-    msr_cm = 0;
-#endif
-#if defined(CONFIG_USER_ONLY)
     msr_pr = 1;
-    tlb_flush(env, 1);
 #else
     env->nip = 0xFFFFFFFC;
     ppc_tlb_invalidate_all(env);
 #endif
     do_compute_hflags(env);
     env->reserve = -1;
+    /* Be sure no exception or interrupt is pending */
+    env->pending_interrupts = 0;
+    env->exception_index = EXCP_NONE;
+    /* Flush all TLBs */
+    tlb_flush(env, 1);
 }
 
 CPUPPCState *cpu_ppc_init (void)

Modified: trunk/src/host/qemu-neo1973/target-ppc/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/op.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -2365,6 +2365,54 @@
     RETURN();
 }
 
+void OPPROTO op_booke_tlbre0 (void)
+{
+    do_booke_tlbre0();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbre1 (void)
+{
+    do_booke_tlbre1();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbre2 (void)
+{
+    do_booke_tlbre2();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbsx (void)
+{
+    do_booke_tlbsx();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbsx_ (void)
+{
+    do_booke_tlbsx_();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbwe0 (void)
+{
+    do_booke_tlbwe0();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbwe1 (void)
+{
+    do_booke_tlbwe1();
+    RETURN();
+}
+
+void OPPROTO op_booke_tlbwe2 (void)
+{
+    do_booke_tlbwe2();
+    RETURN();
+}
+
 void OPPROTO op_4xx_tlbre_lo (void)
 {
     do_4xx_tlbre_lo();

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -2537,7 +2537,8 @@
      * of the ppc or ppc64 one
      */
     if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
-        cpu_abort(env, "TLB size %u < %u are not supported (%d)\n",
+        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
+                  "are not supported (%d)\n",
                   tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
     }
     tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
@@ -2605,4 +2606,151 @@
     }
 #endif
 }
+
+/* BookE TLB management */
+void do_booke_tlbwe0 (void)
+{
+    ppcemb_tlb_t *tlb;
+    target_ulong EPN, size;
+    int do_flush_tlbs;
+
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
+    do_flush_tlbs = 0;
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    EPN = T1 & 0xFFFFFC00;
+    if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
+        do_flush_tlbs = 1;
+    tlb->EPN = EPN;
+    size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
+    if ((tlb->prot & PAGE_VALID) && tlb->size < size)
+        do_flush_tlbs = 1;
+    tlb->size = size;
+    tlb->attr &= ~0x1;
+    tlb->attr |= (T1 >> 8) & 1;
+    if (T1 & 0x200) {
+        tlb->prot |= PAGE_VALID;
+    } else {
+        if (tlb->prot & PAGE_VALID) {
+            tlb->prot &= ~PAGE_VALID;
+            do_flush_tlbs = 1;
+        }
+    }
+    tlb->PID = env->spr[SPR_BOOKE_PID];
+    if (do_flush_tlbs)
+        tlb_flush(env, 1);
+}
+
+void do_booke_tlbwe1 (void)
+{
+    ppcemb_tlb_t *tlb;
+    target_phys_addr_t RPN;
+
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    RPN = T1 & 0xFFFFFC0F;
+    if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
+        tlb_flush(env, 1);
+    tlb->RPN = RPN;
+}
+
+void do_booke_tlbwe2 (void)
+{
+    ppcemb_tlb_t *tlb;
+
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
+    tlb->prot = tlb->prot & PAGE_VALID;
+    if (T1 & 0x1)
+        tlb->prot |= PAGE_READ << 4;
+    if (T1 & 0x2)
+        tlb->prot |= PAGE_WRITE << 4;
+    if (T1 & 0x4)
+        tlb->prot |= PAGE_EXEC << 4;
+    if (T1 & 0x8)
+        tlb->prot |= PAGE_READ;
+    if (T1 & 0x10)
+        tlb->prot |= PAGE_WRITE;
+    if (T1 & 0x20)
+        tlb->prot |= PAGE_EXEC;
+}
+
+void do_booke_tlbsx (void)
+{
+    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
+}
+
+void do_booke_tlbsx_ (void)
+{
+    int tmp = xer_so;
+
+    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
+    if (T0 != -1)
+        tmp |= 0x02;
+    env->crf[0] = tmp;
+}
+
+void do_booke_tlbre0 (void)
+{
+    ppcemb_tlb_t *tlb;
+    int size;
+
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    T0 = tlb->EPN;
+    size = booke_page_size_to_tlb(tlb->size);
+    if (size < 0 || size > 0xF)
+        size = 1;
+    T0 |= size << 4;
+    if (tlb->attr & 0x1)
+        T0 |= 0x100;
+    if (tlb->prot & PAGE_VALID)
+        T0 |= 0x200;
+    env->spr[SPR_BOOKE_PID] = tlb->PID;
+}
+
+void do_booke_tlbre1 (void)
+{
+    ppcemb_tlb_t *tlb;
+
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    T0 = tlb->RPN;
+}
+
+void do_booke_tlbre2 (void)
+{
+    ppcemb_tlb_t *tlb;
+
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    T0 = tlb->attr & ~0x1;
+    if (tlb->prot & (PAGE_READ << 4))
+        T0 |= 0x1;
+    if (tlb->prot & (PAGE_WRITE << 4))
+        T0 |= 0x2;
+    if (tlb->prot & (PAGE_EXEC << 4))
+        T0 |= 0x4;
+    if (tlb->prot & PAGE_READ)
+        T0 |= 0x8;
+    if (tlb->prot & PAGE_WRITE)
+        T0 |= 0x10;
+    if (tlb->prot & PAGE_EXEC)
+        T0 |= 0x20;
+}
 #endif /* !CONFIG_USER_ONLY */

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -156,6 +156,18 @@
 void do_op_602_mfrom (void);
 #endif
 
+/* PowerPC BookE specific helpers */
+#if !defined(CONFIG_USER_ONLY)
+void do_booke_tlbre0 (void);
+void do_booke_tlbre1 (void);
+void do_booke_tlbre2 (void);
+void do_booke_tlbsx (void);
+void do_booke_tlbsx_ (void);
+void do_booke_tlbwe0 (void);
+void do_booke_tlbwe1 (void);
+void do_booke_tlbwe2 (void);
+#endif
+
 /* PowerPC 4xx specific helpers */
 void do_405_check_ov (void);
 void do_405_check_sat (void);

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -37,7 +37,7 @@
 void glue(do_lmw, MEMSUFFIX) (int dst)
 {
     for (; dst < 32; dst++, T0 += 4) {
-        ugpr(dst) = glue(ldl, MEMSUFFIX)((uint32_t)T0);
+        env->gpr[dst] = glue(ldl, MEMSUFFIX)((uint32_t)T0);
     }
 }
 
@@ -45,7 +45,7 @@
 void glue(do_lmw_64, MEMSUFFIX) (int dst)
 {
     for (; dst < 32; dst++, T0 += 4) {
-        ugpr(dst) = glue(ldl, MEMSUFFIX)((uint64_t)T0);
+        env->gpr[dst] = glue(ldl, MEMSUFFIX)((uint64_t)T0);
     }
 }
 #endif
@@ -53,7 +53,7 @@
 void glue(do_stmw, MEMSUFFIX) (int src)
 {
     for (; src < 32; src++, T0 += 4) {
-        glue(stl, MEMSUFFIX)((uint32_t)T0, ugpr(src));
+        glue(stl, MEMSUFFIX)((uint32_t)T0, env->gpr[src]);
     }
 }
 
@@ -61,7 +61,7 @@
 void glue(do_stmw_64, MEMSUFFIX) (int src)
 {
     for (; src < 32; src++, T0 += 4) {
-        glue(stl, MEMSUFFIX)((uint64_t)T0, ugpr(src));
+        glue(stl, MEMSUFFIX)((uint64_t)T0, env->gpr[src]);
     }
 }
 #endif
@@ -69,7 +69,7 @@
 void glue(do_lmw_le, MEMSUFFIX) (int dst)
 {
     for (; dst < 32; dst++, T0 += 4) {
-        ugpr(dst) = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
+        env->gpr[dst] = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
     }
 }
 
@@ -77,7 +77,7 @@
 void glue(do_lmw_le_64, MEMSUFFIX) (int dst)
 {
     for (; dst < 32; dst++, T0 += 4) {
-        ugpr(dst) = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
+        env->gpr[dst] = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
     }
 }
 #endif
@@ -85,7 +85,7 @@
 void glue(do_stmw_le, MEMSUFFIX) (int src)
 {
     for (; src < 32; src++, T0 += 4) {
-        glue(st32r, MEMSUFFIX)((uint32_t)T0, ugpr(src));
+        glue(st32r, MEMSUFFIX)((uint32_t)T0, env->gpr[src]);
     }
 }
 
@@ -93,7 +93,7 @@
 void glue(do_stmw_le_64, MEMSUFFIX) (int src)
 {
     for (; src < 32; src++, T0 += 4) {
-        glue(st32r, MEMSUFFIX)((uint64_t)T0, ugpr(src));
+        glue(st32r, MEMSUFFIX)((uint64_t)T0, env->gpr[src]);
     }
 }
 #endif
@@ -104,7 +104,7 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        ugpr(dst++) = glue(ldl, MEMSUFFIX)((uint32_t)T0);
+        env->gpr[dst++] = glue(ldl, MEMSUFFIX)((uint32_t)T0);
         if (unlikely(dst == 32))
             dst = 0;
     }
@@ -113,7 +113,7 @@
         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
             tmp |= glue(ldub, MEMSUFFIX)((uint32_t)T0) << sh;
         }
-        ugpr(dst) = tmp;
+        env->gpr[dst] = tmp;
     }
 }
 
@@ -124,7 +124,7 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        ugpr(dst++) = glue(ldl, MEMSUFFIX)((uint64_t)T0);
+        env->gpr[dst++] = glue(ldl, MEMSUFFIX)((uint64_t)T0);
         if (unlikely(dst == 32))
             dst = 0;
     }
@@ -133,7 +133,7 @@
         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
             tmp |= glue(ldub, MEMSUFFIX)((uint64_t)T0) << sh;
         }
-        ugpr(dst) = tmp;
+        env->gpr[dst] = tmp;
     }
 }
 #endif
@@ -143,13 +143,13 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        glue(stl, MEMSUFFIX)((uint32_t)T0, ugpr(src++));
+        glue(stl, MEMSUFFIX)((uint32_t)T0, env->gpr[src++]);
         if (unlikely(src == 32))
             src = 0;
     }
     if (unlikely(T1 != 0)) {
         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
-            glue(stb, MEMSUFFIX)((uint32_t)T0, (ugpr(src) >> sh) & 0xFF);
+            glue(stb, MEMSUFFIX)((uint32_t)T0, (env->gpr[src] >> sh) & 0xFF);
     }
 }
 
@@ -159,13 +159,13 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        glue(stl, MEMSUFFIX)((uint64_t)T0, ugpr(src++));
+        glue(stl, MEMSUFFIX)((uint64_t)T0, env->gpr[src++]);
         if (unlikely(src == 32))
             src = 0;
     }
     if (unlikely(T1 != 0)) {
         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
-            glue(stb, MEMSUFFIX)((uint64_t)T0, (ugpr(src) >> sh) & 0xFF);
+            glue(stb, MEMSUFFIX)((uint64_t)T0, (env->gpr[src] >> sh) & 0xFF);
     }
 }
 #endif
@@ -176,7 +176,7 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        ugpr(dst++) = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
+        env->gpr[dst++] = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
         if (unlikely(dst == 32))
             dst = 0;
     }
@@ -185,7 +185,7 @@
         for (sh = 0; T1 > 0; T1--, T0++, sh += 8) {
             tmp |= glue(ldub, MEMSUFFIX)((uint32_t)T0) << sh;
         }
-        ugpr(dst) = tmp;
+        env->gpr[dst] = tmp;
     }
 }
 
@@ -196,7 +196,7 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        ugpr(dst++) = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
+        env->gpr[dst++] = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
         if (unlikely(dst == 32))
             dst = 0;
     }
@@ -205,7 +205,7 @@
         for (sh = 0; T1 > 0; T1--, T0++, sh += 8) {
             tmp |= glue(ldub, MEMSUFFIX)((uint64_t)T0) << sh;
         }
-        ugpr(dst) = tmp;
+        env->gpr[dst] = tmp;
     }
 }
 #endif
@@ -215,13 +215,13 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        glue(st32r, MEMSUFFIX)((uint32_t)T0, ugpr(src++));
+        glue(st32r, MEMSUFFIX)((uint32_t)T0, env->gpr[src++]);
         if (unlikely(src == 32))
             src = 0;
     }
     if (unlikely(T1 != 0)) {
         for (sh = 0; T1 > 0; T1--, T0++, sh += 8)
-            glue(stb, MEMSUFFIX)((uint32_t)T0, (ugpr(src) >> sh) & 0xFF);
+            glue(stb, MEMSUFFIX)((uint32_t)T0, (env->gpr[src] >> sh) & 0xFF);
     }
 }
 
@@ -231,13 +231,13 @@
     int sh;
 
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        glue(st32r, MEMSUFFIX)((uint64_t)T0, ugpr(src++));
+        glue(st32r, MEMSUFFIX)((uint64_t)T0, env->gpr[src++]);
         if (unlikely(src == 32))
             src = 0;
     }
     if (unlikely(T1 != 0)) {
         for (sh = 0; T1 > 0; T1--, T0++, sh += 8)
-            glue(stb, MEMSUFFIX)((uint64_t)T0, (ugpr(src) >> sh) & 0xFF);
+            glue(stb, MEMSUFFIX)((uint64_t)T0, (env->gpr[src] >> sh) & 0xFF);
     }
 }
 #endif
@@ -283,7 +283,7 @@
         c = glue(ldub, MEMSUFFIX)((uint32_t)T0++);
         /* ra (if not 0) and rb are never modified */
         if (likely(reg != rb && (ra == 0 || reg != ra))) {
-            ugpr(reg) = (ugpr(reg) & ~(0xFF << d)) | (c << d);
+            env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
         }
         if (unlikely(c == T2))
             break;

Modified: trunk/src/host/qemu-neo1973/target-ppc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate.c	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate.c	2007-09-20 13:33:19 UTC (rev 3019)
@@ -4618,9 +4618,10 @@
     RET_CHG_FLOW(ctx);
 #endif
 }
+
 /* TLB management - PowerPC 405 implementation */
 /* tlbre */
-GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
+GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4648,7 +4649,7 @@
 }
 
 /* tlbsx - tlbsx. */
-GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
+GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4667,7 +4668,7 @@
 }
 
 /* tlbwe */
-GEN_HANDLER(tlbwe, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
+GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4694,6 +4695,92 @@
 #endif
 }
 
+/* TLB management - PowerPC BookE implementation */
+/* tlbre */
+GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    switch (rB(ctx->opcode)) {
+    case 0:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_booke_tlbre0();
+        gen_op_store_T0_gpr(rD(ctx->opcode));
+        break;
+    case 1:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_booke_tlbre1();
+        gen_op_store_T0_gpr(rD(ctx->opcode));
+        break;
+    case 2:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_booke_tlbre2();
+        gen_op_store_T0_gpr(rD(ctx->opcode));
+        break;
+    default:
+        RET_INVAL(ctx);
+        break;
+    }
+#endif
+}
+
+/* tlbsx - tlbsx. */
+GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_addr_reg_index(ctx);
+    if (Rc(ctx->opcode))
+        gen_op_booke_tlbsx_();
+    else
+        gen_op_booke_tlbsx();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* tlbwe */
+GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    switch (rB(ctx->opcode)) {
+    case 0:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_load_gpr_T1(rS(ctx->opcode));
+        gen_op_booke_tlbwe0();
+        break;
+    case 1:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_load_gpr_T1(rS(ctx->opcode));
+        gen_op_booke_tlbwe1();
+        break;
+    case 2:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_load_gpr_T1(rS(ctx->opcode));
+        gen_op_booke_tlbwe2();
+        break;
+    default:
+        RET_INVAL(ctx);
+        break;
+    }
+#endif
+}
+
 /* wrtee */
 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
 {

Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h	2007-09-20 13:06:00 UTC (rev 3018)
+++ trunk/src/host/qemu-neo1973/vl.h	2007-09-20 13:33:19 UTC (rev 3019)
@@ -93,6 +93,15 @@
 #define tostring(s)	#s
 #endif
 
+#ifndef likely
+#if __GNUC__ < 3
+#define __builtin_expect(x, n) (x)
+#endif
+
+#define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x)   __builtin_expect(!!(x), 0)
+#endif
+
 #ifndef MIN
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif
@@ -1640,8 +1649,6 @@
 void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
 void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
 
-#define unlikely(cond)	__builtin_expect(!!(cond), 0)
-
 #include "hw/pxa.h"
 #include "hw/s3c.h"
 





More information about the commitlog mailing list