target-alpha: Implement RD/WRUNIQUE in the translator

When emulating user-mode only, there's no reason to exit
the translation block to effect a call_pal.  We can generate
a move to/from the unique slot directly.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
index c48a297..edec018 100644
--- a/hw/alpha_palcode.c
+++ b/hw/alpha_palcode.c
@@ -1060,7 +1060,6 @@
 {
     target_long ret;
 
-    qemu_log("%s: palcode %02x\n", __func__, palcode);
     switch (palcode) {
     case 0x83:
         /* CALLSYS */
@@ -1078,14 +1077,14 @@
         break;
     case 0x9E:
         /* RDUNIQUE */
-        env->ir[IR_V0] = env->unique;
         qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
-        break;
+        /* Handled in the translator for usermode.  */
+        abort();
     case 0x9F:
         /* WRUNIQUE */
-        env->unique = env->ir[IR_A0];
-        qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
-        break;
+        qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->ir[IR_A0]);
+        /* Handled in the translator for usermode.  */
+        abort();
     default:
         qemu_log("%s: unhandled palcode %02x\n",
                     __func__, palcode);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index fbcedde..5c08923 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -57,6 +57,9 @@
 static TCGv cpu_fir[31];
 static TCGv cpu_pc;
 static TCGv cpu_lock;
+#ifdef CONFIG_USER_ONLY
+static TCGv cpu_uniq;
+#endif
 
 /* register names */
 static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
@@ -93,6 +96,11 @@
     cpu_lock = tcg_global_mem_new_i64(TCG_AREG0,
                                       offsetof(CPUState, lock), "lock");
 
+#ifdef CONFIG_USER_ONLY
+    cpu_uniq = tcg_global_mem_new_i64(TCG_AREG0,
+                                      offsetof(CPUState, unique), "uniq");
+#endif
+
     /* register helpers */
 #define GEN_HELPER 2
 #include "helper.h"
@@ -751,23 +759,34 @@
     switch (opc) {
     case 0x00:
         /* CALL_PAL */
+#ifdef CONFIG_USER_ONLY
+        if (palcode == 0x9E) {
+            /* RDUNIQUE */
+            tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_uniq);
+            break;
+        } else if (palcode == 0x9F) {
+            /* WRUNIQUE */
+            tcg_gen_mov_i64(cpu_uniq, cpu_ir[IR_A0]);
+            break;
+        }
+#endif
         if (palcode >= 0x80 && palcode < 0xC0) {
             /* Unprivileged PAL call */
             gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
-#if !defined (CONFIG_USER_ONLY)
-        } else if (palcode < 0x40) {
+            ret = 3;
+            break;
+        }
+#ifndef CONFIG_USER_ONLY
+        if (palcode < 0x40) {
             /* Privileged PAL code */
             if (ctx->mem_idx & 1)
                 goto invalid_opc;
-            else
-                gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
-#endif
-        } else {
-            /* Invalid PAL call */
-            goto invalid_opc;
+            gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
+            ret = 3;
         }
-        ret = 3;
-        break;
+#endif
+        /* Invalid PAL call */
+        goto invalid_opc;
     case 0x01:
         /* OPC01 */
         goto invalid_opc;