symbian-qemu-0.9.1-12/qemu-symbian-svp/target-sparc/op_helper.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #include "exec.h"
       
     2 #include "host-utils.h"
       
     3 #include "helper.h"
       
     4 #if !defined(CONFIG_USER_ONLY)
       
     5 #include "softmmu_exec.h"
       
     6 #endif /* !defined(CONFIG_USER_ONLY) */
       
     7 
       
     8 //#define DEBUG_MMU
       
     9 //#define DEBUG_MXCC
       
    10 //#define DEBUG_UNALIGNED
       
    11 //#define DEBUG_UNASSIGNED
       
    12 //#define DEBUG_ASI
       
    13 //#define DEBUG_PCALL
       
    14 
       
    15 #ifdef DEBUG_MMU
       
    16 #define DPRINTF_MMU(fmt, args...) \
       
    17 do { printf("MMU: " fmt , ##args); } while (0)
       
    18 #else
       
    19 #define DPRINTF_MMU(fmt, args...) do {} while (0)
       
    20 #endif
       
    21 
       
    22 #ifdef DEBUG_MXCC
       
    23 #define DPRINTF_MXCC(fmt, args...) \
       
    24 do { printf("MXCC: " fmt , ##args); } while (0)
       
    25 #else
       
    26 #define DPRINTF_MXCC(fmt, args...) do {} while (0)
       
    27 #endif
       
    28 
       
    29 #ifdef DEBUG_ASI
       
    30 #define DPRINTF_ASI(fmt, args...) \
       
    31 do { printf("ASI: " fmt , ##args); } while (0)
       
    32 #else
       
    33 #define DPRINTF_ASI(fmt, args...) do {} while (0)
       
    34 #endif
       
    35 
       
    36 #ifdef TARGET_SPARC64
       
    37 #ifndef TARGET_ABI32
       
    38 #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
       
    39 #else
       
    40 #define AM_CHECK(env1) (1)
       
    41 #endif
       
    42 #endif
       
    43 
       
    44 static inline void address_mask(CPUState *env1, target_ulong *addr)
       
    45 {
       
    46 #ifdef TARGET_SPARC64
       
    47     if (AM_CHECK(env1))
       
    48         *addr &= 0xffffffffULL;
       
    49 #endif
       
    50 }
       
    51 
       
    52 static void raise_exception(int tt)
       
    53 {
       
    54     env->exception_index = tt;
       
    55     cpu_loop_exit();
       
    56 }
       
    57 
       
    58 void HELPER(raise_exception)(int tt)
       
    59 {
       
    60     raise_exception(tt);
       
    61 }
       
    62 
       
    63 static inline void set_cwp(int new_cwp)
       
    64 {
       
    65     cpu_set_cwp(env, new_cwp);
       
    66 }
       
    67 
       
    68 void helper_check_align(target_ulong addr, uint32_t align)
       
    69 {
       
    70     if (addr & align) {
       
    71 #ifdef DEBUG_UNALIGNED
       
    72     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
       
    73            "\n", addr, env->pc);
       
    74 #endif
       
    75         raise_exception(TT_UNALIGNED);
       
    76     }
       
    77 }
       
    78 
       
    79 #define F_HELPER(name, p) void helper_f##name##p(void)
       
    80 
       
    81 #define F_BINOP(name)                                           \
       
    82     float32 helper_f ## name ## s (float32 src1, float32 src2)  \
       
    83     {                                                           \
       
    84         return float32_ ## name (src1, src2, &env->fp_status);  \
       
    85     }                                                           \
       
    86     F_HELPER(name, d)                                           \
       
    87     {                                                           \
       
    88         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
       
    89     }                                                           \
       
    90     F_HELPER(name, q)                                           \
       
    91     {                                                           \
       
    92         QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
       
    93     }
       
    94 
       
    95 F_BINOP(add);
       
    96 F_BINOP(sub);
       
    97 F_BINOP(mul);
       
    98 F_BINOP(div);
       
    99 #undef F_BINOP
       
   100 
       
   101 void helper_fsmuld(float32 src1, float32 src2)
       
   102 {
       
   103     DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
       
   104                       float32_to_float64(src2, &env->fp_status),
       
   105                       &env->fp_status);
       
   106 }
       
   107 
       
   108 void helper_fdmulq(void)
       
   109 {
       
   110     QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
       
   111                        float64_to_float128(DT1, &env->fp_status),
       
   112                        &env->fp_status);
       
   113 }
       
   114 
       
   115 float32 helper_fnegs(float32 src)
       
   116 {
       
   117     return float32_chs(src);
       
   118 }
       
   119 
       
   120 #ifdef TARGET_SPARC64
       
   121 F_HELPER(neg, d)
       
   122 {
       
   123     DT0 = float64_chs(DT1);
       
   124 }
       
   125 
       
   126 F_HELPER(neg, q)
       
   127 {
       
   128     QT0 = float128_chs(QT1);
       
   129 }
       
   130 #endif
       
   131 
       
   132 /* Integer to float conversion.  */
       
   133 float32 helper_fitos(int32_t src)
       
   134 {
       
   135     return int32_to_float32(src, &env->fp_status);
       
   136 }
       
   137 
       
   138 void helper_fitod(int32_t src)
       
   139 {
       
   140     DT0 = int32_to_float64(src, &env->fp_status);
       
   141 }
       
   142 
       
   143 void helper_fitoq(int32_t src)
       
   144 {
       
   145     QT0 = int32_to_float128(src, &env->fp_status);
       
   146 }
       
   147 
       
   148 #ifdef TARGET_SPARC64
       
   149 float32 helper_fxtos(void)
       
   150 {
       
   151     return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
       
   152 }
       
   153 
       
   154 F_HELPER(xto, d)
       
   155 {
       
   156     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
       
   157 }
       
   158 
       
   159 F_HELPER(xto, q)
       
   160 {
       
   161     QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
       
   162 }
       
   163 #endif
       
   164 #undef F_HELPER
       
   165 
       
   166 /* floating point conversion */
       
   167 float32 helper_fdtos(void)
       
   168 {
       
   169     return float64_to_float32(DT1, &env->fp_status);
       
   170 }
       
   171 
       
   172 void helper_fstod(float32 src)
       
   173 {
       
   174     DT0 = float32_to_float64(src, &env->fp_status);
       
   175 }
       
   176 
       
   177 float32 helper_fqtos(void)
       
   178 {
       
   179     return float128_to_float32(QT1, &env->fp_status);
       
   180 }
       
   181 
       
   182 void helper_fstoq(float32 src)
       
   183 {
       
   184     QT0 = float32_to_float128(src, &env->fp_status);
       
   185 }
       
   186 
       
   187 void helper_fqtod(void)
       
   188 {
       
   189     DT0 = float128_to_float64(QT1, &env->fp_status);
       
   190 }
       
   191 
       
   192 void helper_fdtoq(void)
       
   193 {
       
   194     QT0 = float64_to_float128(DT1, &env->fp_status);
       
   195 }
       
   196 
       
   197 /* Float to integer conversion.  */
       
   198 int32_t helper_fstoi(float32 src)
       
   199 {
       
   200     return float32_to_int32_round_to_zero(src, &env->fp_status);
       
   201 }
       
   202 
       
   203 int32_t helper_fdtoi(void)
       
   204 {
       
   205     return float64_to_int32_round_to_zero(DT1, &env->fp_status);
       
   206 }
       
   207 
       
   208 int32_t helper_fqtoi(void)
       
   209 {
       
   210     return float128_to_int32_round_to_zero(QT1, &env->fp_status);
       
   211 }
       
   212 
       
   213 #ifdef TARGET_SPARC64
       
   214 void helper_fstox(float32 src)
       
   215 {
       
   216     *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
       
   217 }
       
   218 
       
   219 void helper_fdtox(void)
       
   220 {
       
   221     *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
       
   222 }
       
   223 
       
   224 void helper_fqtox(void)
       
   225 {
       
   226     *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
       
   227 }
       
   228 
       
   229 void helper_faligndata(void)
       
   230 {
       
   231     uint64_t tmp;
       
   232 
       
   233     tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
       
   234     /* on many architectures a shift of 64 does nothing */
       
   235     if ((env->gsr & 7) != 0) {
       
   236         tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
       
   237     }
       
   238     *((uint64_t *)&DT0) = tmp;
       
   239 }
       
   240 
       
   241 #ifdef WORDS_BIGENDIAN
       
   242 #define VIS_B64(n) b[7 - (n)]
       
   243 #define VIS_W64(n) w[3 - (n)]
       
   244 #define VIS_SW64(n) sw[3 - (n)]
       
   245 #define VIS_L64(n) l[1 - (n)]
       
   246 #define VIS_B32(n) b[3 - (n)]
       
   247 #define VIS_W32(n) w[1 - (n)]
       
   248 #else
       
   249 #define VIS_B64(n) b[n]
       
   250 #define VIS_W64(n) w[n]
       
   251 #define VIS_SW64(n) sw[n]
       
   252 #define VIS_L64(n) l[n]
       
   253 #define VIS_B32(n) b[n]
       
   254 #define VIS_W32(n) w[n]
       
   255 #endif
       
   256 
       
   257 typedef union {
       
   258     uint8_t b[8];
       
   259     uint16_t w[4];
       
   260     int16_t sw[4];
       
   261     uint32_t l[2];
       
   262     float64 d;
       
   263 } vis64;
       
   264 
       
   265 typedef union {
       
   266     uint8_t b[4];
       
   267     uint16_t w[2];
       
   268     uint32_t l;
       
   269     float32 f;
       
   270 } vis32;
       
   271 
       
   272 void helper_fpmerge(void)
       
   273 {
       
   274     vis64 s, d;
       
   275 
       
   276     s.d = DT0;
       
   277     d.d = DT1;
       
   278 
       
   279     // Reverse calculation order to handle overlap
       
   280     d.VIS_B64(7) = s.VIS_B64(3);
       
   281     d.VIS_B64(6) = d.VIS_B64(3);
       
   282     d.VIS_B64(5) = s.VIS_B64(2);
       
   283     d.VIS_B64(4) = d.VIS_B64(2);
       
   284     d.VIS_B64(3) = s.VIS_B64(1);
       
   285     d.VIS_B64(2) = d.VIS_B64(1);
       
   286     d.VIS_B64(1) = s.VIS_B64(0);
       
   287     //d.VIS_B64(0) = d.VIS_B64(0);
       
   288 
       
   289     DT0 = d.d;
       
   290 }
       
   291 
       
   292 void helper_fmul8x16(void)
       
   293 {
       
   294     vis64 s, d;
       
   295     uint32_t tmp;
       
   296 
       
   297     s.d = DT0;
       
   298     d.d = DT1;
       
   299 
       
   300 #define PMUL(r)                                                 \
       
   301     tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
       
   302     if ((tmp & 0xff) > 0x7f)                                    \
       
   303         tmp += 0x100;                                           \
       
   304     d.VIS_W64(r) = tmp >> 8;
       
   305 
       
   306     PMUL(0);
       
   307     PMUL(1);
       
   308     PMUL(2);
       
   309     PMUL(3);
       
   310 #undef PMUL
       
   311 
       
   312     DT0 = d.d;
       
   313 }
       
   314 
       
   315 void helper_fmul8x16al(void)
       
   316 {
       
   317     vis64 s, d;
       
   318     uint32_t tmp;
       
   319 
       
   320     s.d = DT0;
       
   321     d.d = DT1;
       
   322 
       
   323 #define PMUL(r)                                                 \
       
   324     tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
       
   325     if ((tmp & 0xff) > 0x7f)                                    \
       
   326         tmp += 0x100;                                           \
       
   327     d.VIS_W64(r) = tmp >> 8;
       
   328 
       
   329     PMUL(0);
       
   330     PMUL(1);
       
   331     PMUL(2);
       
   332     PMUL(3);
       
   333 #undef PMUL
       
   334 
       
   335     DT0 = d.d;
       
   336 }
       
   337 
       
   338 void helper_fmul8x16au(void)
       
   339 {
       
   340     vis64 s, d;
       
   341     uint32_t tmp;
       
   342 
       
   343     s.d = DT0;
       
   344     d.d = DT1;
       
   345 
       
   346 #define PMUL(r)                                                 \
       
   347     tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
       
   348     if ((tmp & 0xff) > 0x7f)                                    \
       
   349         tmp += 0x100;                                           \
       
   350     d.VIS_W64(r) = tmp >> 8;
       
   351 
       
   352     PMUL(0);
       
   353     PMUL(1);
       
   354     PMUL(2);
       
   355     PMUL(3);
       
   356 #undef PMUL
       
   357 
       
   358     DT0 = d.d;
       
   359 }
       
   360 
       
   361 void helper_fmul8sux16(void)
       
   362 {
       
   363     vis64 s, d;
       
   364     uint32_t tmp;
       
   365 
       
   366     s.d = DT0;
       
   367     d.d = DT1;
       
   368 
       
   369 #define PMUL(r)                                                         \
       
   370     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
       
   371     if ((tmp & 0xff) > 0x7f)                                            \
       
   372         tmp += 0x100;                                                   \
       
   373     d.VIS_W64(r) = tmp >> 8;
       
   374 
       
   375     PMUL(0);
       
   376     PMUL(1);
       
   377     PMUL(2);
       
   378     PMUL(3);
       
   379 #undef PMUL
       
   380 
       
   381     DT0 = d.d;
       
   382 }
       
   383 
       
   384 void helper_fmul8ulx16(void)
       
   385 {
       
   386     vis64 s, d;
       
   387     uint32_t tmp;
       
   388 
       
   389     s.d = DT0;
       
   390     d.d = DT1;
       
   391 
       
   392 #define PMUL(r)                                                         \
       
   393     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
       
   394     if ((tmp & 0xff) > 0x7f)                                            \
       
   395         tmp += 0x100;                                                   \
       
   396     d.VIS_W64(r) = tmp >> 8;
       
   397 
       
   398     PMUL(0);
       
   399     PMUL(1);
       
   400     PMUL(2);
       
   401     PMUL(3);
       
   402 #undef PMUL
       
   403 
       
   404     DT0 = d.d;
       
   405 }
       
   406 
       
   407 void helper_fmuld8sux16(void)
       
   408 {
       
   409     vis64 s, d;
       
   410     uint32_t tmp;
       
   411 
       
   412     s.d = DT0;
       
   413     d.d = DT1;
       
   414 
       
   415 #define PMUL(r)                                                         \
       
   416     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
       
   417     if ((tmp & 0xff) > 0x7f)                                            \
       
   418         tmp += 0x100;                                                   \
       
   419     d.VIS_L64(r) = tmp;
       
   420 
       
   421     // Reverse calculation order to handle overlap
       
   422     PMUL(1);
       
   423     PMUL(0);
       
   424 #undef PMUL
       
   425 
       
   426     DT0 = d.d;
       
   427 }
       
   428 
       
   429 void helper_fmuld8ulx16(void)
       
   430 {
       
   431     vis64 s, d;
       
   432     uint32_t tmp;
       
   433 
       
   434     s.d = DT0;
       
   435     d.d = DT1;
       
   436 
       
   437 #define PMUL(r)                                                         \
       
   438     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
       
   439     if ((tmp & 0xff) > 0x7f)                                            \
       
   440         tmp += 0x100;                                                   \
       
   441     d.VIS_L64(r) = tmp;
       
   442 
       
   443     // Reverse calculation order to handle overlap
       
   444     PMUL(1);
       
   445     PMUL(0);
       
   446 #undef PMUL
       
   447 
       
   448     DT0 = d.d;
       
   449 }
       
   450 
       
   451 void helper_fexpand(void)
       
   452 {
       
   453     vis32 s;
       
   454     vis64 d;
       
   455 
       
   456     s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
       
   457     d.d = DT1;
       
   458     d.VIS_W64(0) = s.VIS_B32(0) << 4;
       
   459     d.VIS_W64(1) = s.VIS_B32(1) << 4;
       
   460     d.VIS_W64(2) = s.VIS_B32(2) << 4;
       
   461     d.VIS_W64(3) = s.VIS_B32(3) << 4;
       
   462 
       
   463     DT0 = d.d;
       
   464 }
       
   465 
       
   466 #define VIS_HELPER(name, F)                             \
       
   467     void name##16(void)                                 \
       
   468     {                                                   \
       
   469         vis64 s, d;                                     \
       
   470                                                         \
       
   471         s.d = DT0;                                      \
       
   472         d.d = DT1;                                      \
       
   473                                                         \
       
   474         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
       
   475         d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
       
   476         d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
       
   477         d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
       
   478                                                         \
       
   479         DT0 = d.d;                                      \
       
   480     }                                                   \
       
   481                                                         \
       
   482     uint32_t name##16s(uint32_t src1, uint32_t src2)    \
       
   483     {                                                   \
       
   484         vis32 s, d;                                     \
       
   485                                                         \
       
   486         s.l = src1;                                     \
       
   487         d.l = src2;                                     \
       
   488                                                         \
       
   489         d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
       
   490         d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
       
   491                                                         \
       
   492         return d.l;                                     \
       
   493     }                                                   \
       
   494                                                         \
       
   495     void name##32(void)                                 \
       
   496     {                                                   \
       
   497         vis64 s, d;                                     \
       
   498                                                         \
       
   499         s.d = DT0;                                      \
       
   500         d.d = DT1;                                      \
       
   501                                                         \
       
   502         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
       
   503         d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
       
   504                                                         \
       
   505         DT0 = d.d;                                      \
       
   506     }                                                   \
       
   507                                                         \
       
   508     uint32_t name##32s(uint32_t src1, uint32_t src2)    \
       
   509     {                                                   \
       
   510         vis32 s, d;                                     \
       
   511                                                         \
       
   512         s.l = src1;                                     \
       
   513         d.l = src2;                                     \
       
   514                                                         \
       
   515         d.l = F(d.l, s.l);                              \
       
   516                                                         \
       
   517         return d.l;                                     \
       
   518     }
       
   519 
       
   520 #define FADD(a, b) ((a) + (b))
       
   521 #define FSUB(a, b) ((a) - (b))
       
   522 VIS_HELPER(helper_fpadd, FADD)
       
   523 VIS_HELPER(helper_fpsub, FSUB)
       
   524 
       
   525 #define VIS_CMPHELPER(name, F)                                        \
       
   526     void name##16(void)                                           \
       
   527     {                                                             \
       
   528         vis64 s, d;                                               \
       
   529                                                                   \
       
   530         s.d = DT0;                                                \
       
   531         d.d = DT1;                                                \
       
   532                                                                   \
       
   533         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
       
   534         d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
       
   535         d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
       
   536         d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
       
   537                                                                   \
       
   538         DT0 = d.d;                                                \
       
   539     }                                                             \
       
   540                                                                   \
       
   541     void name##32(void)                                           \
       
   542     {                                                             \
       
   543         vis64 s, d;                                               \
       
   544                                                                   \
       
   545         s.d = DT0;                                                \
       
   546         d.d = DT1;                                                \
       
   547                                                                   \
       
   548         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
       
   549         d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
       
   550                                                                   \
       
   551         DT0 = d.d;                                                \
       
   552     }
       
   553 
       
   554 #define FCMPGT(a, b) ((a) > (b))
       
   555 #define FCMPEQ(a, b) ((a) == (b))
       
   556 #define FCMPLE(a, b) ((a) <= (b))
       
   557 #define FCMPNE(a, b) ((a) != (b))
       
   558 
       
   559 VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
       
   560 VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
       
   561 VIS_CMPHELPER(helper_fcmple, FCMPLE)
       
   562 VIS_CMPHELPER(helper_fcmpne, FCMPNE)
       
   563 #endif
       
   564 
       
   565 void helper_check_ieee_exceptions(void)
       
   566 {
       
   567     target_ulong status;
       
   568 
       
   569     status = get_float_exception_flags(&env->fp_status);
       
   570     if (status) {
       
   571         /* Copy IEEE 754 flags into FSR */
       
   572         if (status & float_flag_invalid)
       
   573             env->fsr |= FSR_NVC;
       
   574         if (status & float_flag_overflow)
       
   575             env->fsr |= FSR_OFC;
       
   576         if (status & float_flag_underflow)
       
   577             env->fsr |= FSR_UFC;
       
   578         if (status & float_flag_divbyzero)
       
   579             env->fsr |= FSR_DZC;
       
   580         if (status & float_flag_inexact)
       
   581             env->fsr |= FSR_NXC;
       
   582 
       
   583         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
       
   584             /* Unmasked exception, generate a trap */
       
   585             env->fsr |= FSR_FTT_IEEE_EXCP;
       
   586             raise_exception(TT_FP_EXCP);
       
   587         } else {
       
   588             /* Accumulate exceptions */
       
   589             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
       
   590         }
       
   591     }
       
   592 }
       
   593 
       
   594 void helper_clear_float_exceptions(void)
       
   595 {
       
   596     set_float_exception_flags(0, &env->fp_status);
       
   597 }
       
   598 
       
   599 float32 helper_fabss(float32 src)
       
   600 {
       
   601     return float32_abs(src);
       
   602 }
       
   603 
       
   604 #ifdef TARGET_SPARC64
       
   605 void helper_fabsd(void)
       
   606 {
       
   607     DT0 = float64_abs(DT1);
       
   608 }
       
   609 
       
   610 void helper_fabsq(void)
       
   611 {
       
   612     QT0 = float128_abs(QT1);
       
   613 }
       
   614 #endif
       
   615 
       
   616 float32 helper_fsqrts(float32 src)
       
   617 {
       
   618     return float32_sqrt(src, &env->fp_status);
       
   619 }
       
   620 
       
   621 void helper_fsqrtd(void)
       
   622 {
       
   623     DT0 = float64_sqrt(DT1, &env->fp_status);
       
   624 }
       
   625 
       
   626 void helper_fsqrtq(void)
       
   627 {
       
   628     QT0 = float128_sqrt(QT1, &env->fp_status);
       
   629 }
       
   630 
       
   631 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
       
   632     void glue(helper_, name) (void)                                     \
       
   633     {                                                                   \
       
   634         target_ulong new_fsr;                                           \
       
   635                                                                         \
       
   636         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
       
   637         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
       
   638         case float_relation_unordered:                                  \
       
   639             new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
       
   640             if ((env->fsr & FSR_NVM) || TRAP) {                         \
       
   641                 env->fsr |= new_fsr;                                    \
       
   642                 env->fsr |= FSR_NVC;                                    \
       
   643                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
       
   644                 raise_exception(TT_FP_EXCP);                            \
       
   645             } else {                                                    \
       
   646                 env->fsr |= FSR_NVA;                                    \
       
   647             }                                                           \
       
   648             break;                                                      \
       
   649         case float_relation_less:                                       \
       
   650             new_fsr = FSR_FCC0 << FS;                                   \
       
   651             break;                                                      \
       
   652         case float_relation_greater:                                    \
       
   653             new_fsr = FSR_FCC1 << FS;                                   \
       
   654             break;                                                      \
       
   655         default:                                                        \
       
   656             new_fsr = 0;                                                \
       
   657             break;                                                      \
       
   658         }                                                               \
       
   659         env->fsr |= new_fsr;                                            \
       
   660     }
       
   661 #define GEN_FCMPS(name, size, FS, TRAP)                                 \
       
   662     void glue(helper_, name)(float32 src1, float32 src2)                \
       
   663     {                                                                   \
       
   664         target_ulong new_fsr;                                           \
       
   665                                                                         \
       
   666         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
       
   667         switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
       
   668         case float_relation_unordered:                                  \
       
   669             new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
       
   670             if ((env->fsr & FSR_NVM) || TRAP) {                         \
       
   671                 env->fsr |= new_fsr;                                    \
       
   672                 env->fsr |= FSR_NVC;                                    \
       
   673                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
       
   674                 raise_exception(TT_FP_EXCP);                            \
       
   675             } else {                                                    \
       
   676                 env->fsr |= FSR_NVA;                                    \
       
   677             }                                                           \
       
   678             break;                                                      \
       
   679         case float_relation_less:                                       \
       
   680             new_fsr = FSR_FCC0 << FS;                                   \
       
   681             break;                                                      \
       
   682         case float_relation_greater:                                    \
       
   683             new_fsr = FSR_FCC1 << FS;                                   \
       
   684             break;                                                      \
       
   685         default:                                                        \
       
   686             new_fsr = 0;                                                \
       
   687             break;                                                      \
       
   688         }                                                               \
       
   689         env->fsr |= new_fsr;                                            \
       
   690     }
       
   691 
       
   692 GEN_FCMPS(fcmps, float32, 0, 0);
       
   693 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
       
   694 
       
   695 GEN_FCMPS(fcmpes, float32, 0, 1);
       
   696 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
       
   697 
       
   698 GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
       
   699 GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
       
   700 
       
   701 #ifdef TARGET_SPARC64
       
   702 GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
       
   703 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
       
   704 GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
       
   705 
       
   706 GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
       
   707 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
       
   708 GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
       
   709 
       
   710 GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
       
   711 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
       
   712 GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
       
   713 
       
   714 GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
       
   715 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
       
   716 GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
       
   717 
       
   718 GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
       
   719 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
       
   720 GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
       
   721 
       
   722 GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
       
   723 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
       
   724 GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
       
   725 #endif
       
   726 #undef GEN_FCMPS
       
   727 
       
   728 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
       
   729     defined(DEBUG_MXCC)
       
   730 static void dump_mxcc(CPUState *env)
       
   731 {
       
   732     printf("mxccdata: %016llx %016llx %016llx %016llx\n",
       
   733            env->mxccdata[0], env->mxccdata[1],
       
   734            env->mxccdata[2], env->mxccdata[3]);
       
   735     printf("mxccregs: %016llx %016llx %016llx %016llx\n"
       
   736            "          %016llx %016llx %016llx %016llx\n",
       
   737            env->mxccregs[0], env->mxccregs[1],
       
   738            env->mxccregs[2], env->mxccregs[3],
       
   739            env->mxccregs[4], env->mxccregs[5],
       
   740            env->mxccregs[6], env->mxccregs[7]);
       
   741 }
       
   742 #endif
       
   743 
       
   744 #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
       
   745     && defined(DEBUG_ASI)
       
   746 static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
       
   747                      uint64_t r1)
       
   748 {
       
   749     switch (size)
       
   750     {
       
   751     case 1:
       
   752         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
       
   753                     addr, asi, r1 & 0xff);
       
   754         break;
       
   755     case 2:
       
   756         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
       
   757                     addr, asi, r1 & 0xffff);
       
   758         break;
       
   759     case 4:
       
   760         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
       
   761                     addr, asi, r1 & 0xffffffff);
       
   762         break;
       
   763     case 8:
       
   764         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
       
   765                     addr, asi, r1);
       
   766         break;
       
   767     }
       
   768 }
       
   769 #endif
       
   770 
       
   771 #ifndef TARGET_SPARC64
       
   772 #ifndef CONFIG_USER_ONLY
       
   773 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
       
   774 {
       
   775     uint64_t ret = 0;
       
   776 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
       
   777     uint32_t last_addr = addr;
       
   778 #endif
       
   779 
       
   780     helper_check_align(addr, size - 1);
       
   781     switch (asi) {
       
   782     case 2: /* SuperSparc MXCC registers */
       
   783         switch (addr) {
       
   784         case 0x01c00a00: /* MXCC control register */
       
   785             if (size == 8)
       
   786                 ret = env->mxccregs[3];
       
   787             else
       
   788                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
   789                              size);
       
   790             break;
       
   791         case 0x01c00a04: /* MXCC control register */
       
   792             if (size == 4)
       
   793                 ret = env->mxccregs[3];
       
   794             else
       
   795                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
   796                              size);
       
   797             break;
       
   798         case 0x01c00c00: /* Module reset register */
       
   799             if (size == 8) {
       
   800                 ret = env->mxccregs[5];
       
   801                 // should we do something here?
       
   802             } else
       
   803                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
   804                              size);
       
   805             break;
       
   806         case 0x01c00f00: /* MBus port address register */
       
   807             if (size == 8)
       
   808                 ret = env->mxccregs[7];
       
   809             else
       
   810                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
   811                              size);
       
   812             break;
       
   813         default:
       
   814             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
       
   815                          size);
       
   816             break;
       
   817         }
       
   818         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
       
   819                      "addr = %08x -> ret = %" PRIx64 ","
       
   820                      "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
       
   821 #ifdef DEBUG_MXCC
       
   822         dump_mxcc(env);
       
   823 #endif
       
   824         break;
       
   825     case 3: /* MMU probe */
       
   826         {
       
   827             int mmulev;
       
   828 
       
   829             mmulev = (addr >> 8) & 15;
       
   830             if (mmulev > 4)
       
   831                 ret = 0;
       
   832             else
       
   833                 ret = mmu_probe(env, addr, mmulev);
       
   834             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
       
   835                         addr, mmulev, ret);
       
   836         }
       
   837         break;
       
   838     case 4: /* read MMU regs */
       
   839         {
       
   840             int reg = (addr >> 8) & 0x1f;
       
   841 
       
   842             ret = env->mmuregs[reg];
       
   843             if (reg == 3) /* Fault status cleared on read */
       
   844                 env->mmuregs[3] = 0;
       
   845             else if (reg == 0x13) /* Fault status read */
       
   846                 ret = env->mmuregs[3];
       
   847             else if (reg == 0x14) /* Fault address read */
       
   848                 ret = env->mmuregs[4];
       
   849             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
       
   850         }
       
   851         break;
       
   852     case 5: // Turbosparc ITLB Diagnostic
       
   853     case 6: // Turbosparc DTLB Diagnostic
       
   854     case 7: // Turbosparc IOTLB Diagnostic
       
   855         break;
       
   856     case 9: /* Supervisor code access */
       
   857         switch(size) {
       
   858         case 1:
       
   859             ret = ldub_code(addr);
       
   860             break;
       
   861         case 2:
       
   862             ret = lduw_code(addr);
       
   863             break;
       
   864         default:
       
   865         case 4:
       
   866             ret = ldl_code(addr);
       
   867             break;
       
   868         case 8:
       
   869             ret = ldq_code(addr);
       
   870             break;
       
   871         }
       
   872         break;
       
   873     case 0xa: /* User data access */
       
   874         switch(size) {
       
   875         case 1:
       
   876             ret = ldub_user(addr);
       
   877             break;
       
   878         case 2:
       
   879             ret = lduw_user(addr);
       
   880             break;
       
   881         default:
       
   882         case 4:
       
   883             ret = ldl_user(addr);
       
   884             break;
       
   885         case 8:
       
   886             ret = ldq_user(addr);
       
   887             break;
       
   888         }
       
   889         break;
       
   890     case 0xb: /* Supervisor data access */
       
   891         switch(size) {
       
   892         case 1:
       
   893             ret = ldub_kernel(addr);
       
   894             break;
       
   895         case 2:
       
   896             ret = lduw_kernel(addr);
       
   897             break;
       
   898         default:
       
   899         case 4:
       
   900             ret = ldl_kernel(addr);
       
   901             break;
       
   902         case 8:
       
   903             ret = ldq_kernel(addr);
       
   904             break;
       
   905         }
       
   906         break;
       
   907     case 0xc: /* I-cache tag */
       
   908     case 0xd: /* I-cache data */
       
   909     case 0xe: /* D-cache tag */
       
   910     case 0xf: /* D-cache data */
       
   911         break;
       
   912     case 0x20: /* MMU passthrough */
       
   913         switch(size) {
       
   914         case 1:
       
   915             ret = ldub_phys(addr);
       
   916             break;
       
   917         case 2:
       
   918             ret = lduw_phys(addr);
       
   919             break;
       
   920         default:
       
   921         case 4:
       
   922             ret = ldl_phys(addr);
       
   923             break;
       
   924         case 8:
       
   925             ret = ldq_phys(addr);
       
   926             break;
       
   927         }
       
   928         break;
       
   929     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
       
   930         switch(size) {
       
   931         case 1:
       
   932             ret = ldub_phys((target_phys_addr_t)addr
       
   933                             | ((target_phys_addr_t)(asi & 0xf) << 32));
       
   934             break;
       
   935         case 2:
       
   936             ret = lduw_phys((target_phys_addr_t)addr
       
   937                             | ((target_phys_addr_t)(asi & 0xf) << 32));
       
   938             break;
       
   939         default:
       
   940         case 4:
       
   941             ret = ldl_phys((target_phys_addr_t)addr
       
   942                            | ((target_phys_addr_t)(asi & 0xf) << 32));
       
   943             break;
       
   944         case 8:
       
   945             ret = ldq_phys((target_phys_addr_t)addr
       
   946                            | ((target_phys_addr_t)(asi & 0xf) << 32));
       
   947             break;
       
   948         }
       
   949         break;
       
   950     case 0x30: // Turbosparc secondary cache diagnostic
       
   951     case 0x31: // Turbosparc RAM snoop
       
   952     case 0x32: // Turbosparc page table descriptor diagnostic
       
   953     case 0x39: /* data cache diagnostic register */
       
   954         ret = 0;
       
   955         break;
       
   956     case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
       
   957         {
       
   958             int reg = (addr >> 8) & 3;
       
   959 
       
   960             switch(reg) {
       
   961             case 0: /* Breakpoint Value (Addr) */
       
   962                 ret = env->mmubpregs[reg];
       
   963                 break;
       
   964             case 1: /* Breakpoint Mask */
       
   965                 ret = env->mmubpregs[reg];
       
   966                 break;
       
   967             case 2: /* Breakpoint Control */
       
   968                 ret = env->mmubpregs[reg];
       
   969                 break;
       
   970             case 3: /* Breakpoint Status */
       
   971                 ret = env->mmubpregs[reg];
       
   972                 env->mmubpregs[reg] = 0ULL;
       
   973                 break;
       
   974             }
       
   975             DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
       
   976         }
       
   977         break;
       
   978     case 8: /* User code access, XXX */
       
   979     default:
       
   980         do_unassigned_access(addr, 0, 0, asi, size);
       
   981         ret = 0;
       
   982         break;
       
   983     }
       
   984     if (sign) {
       
   985         switch(size) {
       
   986         case 1:
       
   987             ret = (int8_t) ret;
       
   988             break;
       
   989         case 2:
       
   990             ret = (int16_t) ret;
       
   991             break;
       
   992         case 4:
       
   993             ret = (int32_t) ret;
       
   994             break;
       
   995         default:
       
   996             break;
       
   997         }
       
   998     }
       
   999 #ifdef DEBUG_ASI
       
  1000     dump_asi("read ", last_addr, asi, size, ret);
       
  1001 #endif
       
  1002     return ret;
       
  1003 }
       
  1004 
       
  1005 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
       
  1006 {
       
  1007     helper_check_align(addr, size - 1);
       
  1008     switch(asi) {
       
  1009     case 2: /* SuperSparc MXCC registers */
       
  1010         switch (addr) {
       
  1011         case 0x01c00000: /* MXCC stream data register 0 */
       
  1012             if (size == 8)
       
  1013                 env->mxccdata[0] = val;
       
  1014             else
       
  1015                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1016                              size);
       
  1017             break;
       
  1018         case 0x01c00008: /* MXCC stream data register 1 */
       
  1019             if (size == 8)
       
  1020                 env->mxccdata[1] = val;
       
  1021             else
       
  1022                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1023                              size);
       
  1024             break;
       
  1025         case 0x01c00010: /* MXCC stream data register 2 */
       
  1026             if (size == 8)
       
  1027                 env->mxccdata[2] = val;
       
  1028             else
       
  1029                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1030                              size);
       
  1031             break;
       
  1032         case 0x01c00018: /* MXCC stream data register 3 */
       
  1033             if (size == 8)
       
  1034                 env->mxccdata[3] = val;
       
  1035             else
       
  1036                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1037                              size);
       
  1038             break;
       
  1039         case 0x01c00100: /* MXCC stream source */
       
  1040             if (size == 8)
       
  1041                 env->mxccregs[0] = val;
       
  1042             else
       
  1043                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1044                              size);
       
  1045             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
       
  1046                                         0);
       
  1047             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
       
  1048                                         8);
       
  1049             env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
       
  1050                                         16);
       
  1051             env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
       
  1052                                         24);
       
  1053             break;
       
  1054         case 0x01c00200: /* MXCC stream destination */
       
  1055             if (size == 8)
       
  1056                 env->mxccregs[1] = val;
       
  1057             else
       
  1058                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1059                              size);
       
  1060             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
       
  1061                      env->mxccdata[0]);
       
  1062             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
       
  1063                      env->mxccdata[1]);
       
  1064             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
       
  1065                      env->mxccdata[2]);
       
  1066             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
       
  1067                      env->mxccdata[3]);
       
  1068             break;
       
  1069         case 0x01c00a00: /* MXCC control register */
       
  1070             if (size == 8)
       
  1071                 env->mxccregs[3] = val;
       
  1072             else
       
  1073                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1074                              size);
       
  1075             break;
       
  1076         case 0x01c00a04: /* MXCC control register */
       
  1077             if (size == 4)
       
  1078                 env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
       
  1079                     | val;
       
  1080             else
       
  1081                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1082                              size);
       
  1083             break;
       
  1084         case 0x01c00e00: /* MXCC error register  */
       
  1085             // writing a 1 bit clears the error
       
  1086             if (size == 8)
       
  1087                 env->mxccregs[6] &= ~val;
       
  1088             else
       
  1089                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1090                              size);
       
  1091             break;
       
  1092         case 0x01c00f00: /* MBus port address register */
       
  1093             if (size == 8)
       
  1094                 env->mxccregs[7] = val;
       
  1095             else
       
  1096                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
       
  1097                              size);
       
  1098             break;
       
  1099         default:
       
  1100             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
       
  1101                          size);
       
  1102             break;
       
  1103         }
       
  1104         DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
       
  1105                      asi, size, addr, val);
       
  1106 #ifdef DEBUG_MXCC
       
  1107         dump_mxcc(env);
       
  1108 #endif
       
  1109         break;
       
  1110     case 3: /* MMU flush */
       
  1111         {
       
  1112             int mmulev;
       
  1113 
       
  1114             mmulev = (addr >> 8) & 15;
       
  1115             DPRINTF_MMU("mmu flush level %d\n", mmulev);
       
  1116             switch (mmulev) {
       
  1117             case 0: // flush page
       
  1118                 tlb_flush_page(env, addr & 0xfffff000);
       
  1119                 break;
       
  1120             case 1: // flush segment (256k)
       
  1121             case 2: // flush region (16M)
       
  1122             case 3: // flush context (4G)
       
  1123             case 4: // flush entire
       
  1124                 tlb_flush(env, 1);
       
  1125                 break;
       
  1126             default:
       
  1127                 break;
       
  1128             }
       
  1129 #ifdef DEBUG_MMU
       
  1130             dump_mmu(env);
       
  1131 #endif
       
  1132         }
       
  1133         break;
       
  1134     case 4: /* write MMU regs */
       
  1135         {
       
  1136             int reg = (addr >> 8) & 0x1f;
       
  1137             uint32_t oldreg;
       
  1138 
       
  1139             oldreg = env->mmuregs[reg];
       
  1140             switch(reg) {
       
  1141             case 0: // Control Register
       
  1142                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
       
  1143                                     (val & 0x00ffffff);
       
  1144                 // Mappings generated during no-fault mode or MMU
       
  1145                 // disabled mode are invalid in normal mode
       
  1146                 if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
       
  1147                     (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
       
  1148                     tlb_flush(env, 1);
       
  1149                 break;
       
  1150             case 1: // Context Table Pointer Register
       
  1151                 env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
       
  1152                 break;
       
  1153             case 2: // Context Register
       
  1154                 env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
       
  1155                 if (oldreg != env->mmuregs[reg]) {
       
  1156                     /* we flush when the MMU context changes because
       
  1157                        QEMU has no MMU context support */
       
  1158                     tlb_flush(env, 1);
       
  1159                 }
       
  1160                 break;
       
  1161             case 3: // Synchronous Fault Status Register with Clear
       
  1162             case 4: // Synchronous Fault Address Register
       
  1163                 break;
       
  1164             case 0x10: // TLB Replacement Control Register
       
  1165                 env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
       
  1166                 break;
       
  1167             case 0x13: // Synchronous Fault Status Register with Read and Clear
       
  1168                 env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
       
  1169                 break;
       
  1170             case 0x14: // Synchronous Fault Address Register
       
  1171                 env->mmuregs[4] = val;
       
  1172                 break;
       
  1173             default:
       
  1174                 env->mmuregs[reg] = val;
       
  1175                 break;
       
  1176             }
       
  1177             if (oldreg != env->mmuregs[reg]) {
       
  1178                 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
       
  1179                             reg, oldreg, env->mmuregs[reg]);
       
  1180             }
       
  1181 #ifdef DEBUG_MMU
       
  1182             dump_mmu(env);
       
  1183 #endif
       
  1184         }
       
  1185         break;
       
  1186     case 5: // Turbosparc ITLB Diagnostic
       
  1187     case 6: // Turbosparc DTLB Diagnostic
       
  1188     case 7: // Turbosparc IOTLB Diagnostic
       
  1189         break;
       
  1190     case 0xa: /* User data access */
       
  1191         switch(size) {
       
  1192         case 1:
       
  1193             stb_user(addr, val);
       
  1194             break;
       
  1195         case 2:
       
  1196             stw_user(addr, val);
       
  1197             break;
       
  1198         default:
       
  1199         case 4:
       
  1200             stl_user(addr, val);
       
  1201             break;
       
  1202         case 8:
       
  1203             stq_user(addr, val);
       
  1204             break;
       
  1205         }
       
  1206         break;
       
  1207     case 0xb: /* Supervisor data access */
       
  1208         switch(size) {
       
  1209         case 1:
       
  1210             stb_kernel(addr, val);
       
  1211             break;
       
  1212         case 2:
       
  1213             stw_kernel(addr, val);
       
  1214             break;
       
  1215         default:
       
  1216         case 4:
       
  1217             stl_kernel(addr, val);
       
  1218             break;
       
  1219         case 8:
       
  1220             stq_kernel(addr, val);
       
  1221             break;
       
  1222         }
       
  1223         break;
       
  1224     case 0xc: /* I-cache tag */
       
  1225     case 0xd: /* I-cache data */
       
  1226     case 0xe: /* D-cache tag */
       
  1227     case 0xf: /* D-cache data */
       
  1228     case 0x10: /* I/D-cache flush page */
       
  1229     case 0x11: /* I/D-cache flush segment */
       
  1230     case 0x12: /* I/D-cache flush region */
       
  1231     case 0x13: /* I/D-cache flush context */
       
  1232     case 0x14: /* I/D-cache flush user */
       
  1233         break;
       
  1234     case 0x17: /* Block copy, sta access */
       
  1235         {
       
  1236             // val = src
       
  1237             // addr = dst
       
  1238             // copy 32 bytes
       
  1239             unsigned int i;
       
  1240             uint32_t src = val & ~3, dst = addr & ~3, temp;
       
  1241 
       
  1242             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
       
  1243                 temp = ldl_kernel(src);
       
  1244                 stl_kernel(dst, temp);
       
  1245             }
       
  1246         }
       
  1247         break;
       
  1248     case 0x1f: /* Block fill, stda access */
       
  1249         {
       
  1250             // addr = dst
       
  1251             // fill 32 bytes with val
       
  1252             unsigned int i;
       
  1253             uint32_t dst = addr & 7;
       
  1254 
       
  1255             for (i = 0; i < 32; i += 8, dst += 8)
       
  1256                 stq_kernel(dst, val);
       
  1257         }
       
  1258         break;
       
  1259     case 0x20: /* MMU passthrough */
       
  1260         {
       
  1261             switch(size) {
       
  1262             case 1:
       
  1263                 stb_phys(addr, val);
       
  1264                 break;
       
  1265             case 2:
       
  1266                 stw_phys(addr, val);
       
  1267                 break;
       
  1268             case 4:
       
  1269             default:
       
  1270                 stl_phys(addr, val);
       
  1271                 break;
       
  1272             case 8:
       
  1273                 stq_phys(addr, val);
       
  1274                 break;
       
  1275             }
       
  1276         }
       
  1277         break;
       
  1278     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
       
  1279         {
       
  1280             switch(size) {
       
  1281             case 1:
       
  1282                 stb_phys((target_phys_addr_t)addr
       
  1283                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
       
  1284                 break;
       
  1285             case 2:
       
  1286                 stw_phys((target_phys_addr_t)addr
       
  1287                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
       
  1288                 break;
       
  1289             case 4:
       
  1290             default:
       
  1291                 stl_phys((target_phys_addr_t)addr
       
  1292                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
       
  1293                 break;
       
  1294             case 8:
       
  1295                 stq_phys((target_phys_addr_t)addr
       
  1296                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
       
  1297                 break;
       
  1298             }
       
  1299         }
       
  1300         break;
       
  1301     case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
       
  1302     case 0x31: // store buffer data, Ross RT620 I-cache flush or
       
  1303                // Turbosparc snoop RAM
       
  1304     case 0x32: // store buffer control or Turbosparc page table
       
  1305                // descriptor diagnostic
       
  1306     case 0x36: /* I-cache flash clear */
       
  1307     case 0x37: /* D-cache flash clear */
       
  1308     case 0x4c: /* breakpoint action */
       
  1309         break;
       
  1310     case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
       
  1311         {
       
  1312             int reg = (addr >> 8) & 3;
       
  1313 
       
  1314             switch(reg) {
       
  1315             case 0: /* Breakpoint Value (Addr) */
       
  1316                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
       
  1317                 break;
       
  1318             case 1: /* Breakpoint Mask */
       
  1319                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
       
  1320                 break;
       
  1321             case 2: /* Breakpoint Control */
       
  1322                 env->mmubpregs[reg] = (val & 0x7fULL);
       
  1323                 break;
       
  1324             case 3: /* Breakpoint Status */
       
  1325                 env->mmubpregs[reg] = (val & 0xfULL);
       
  1326                 break;
       
  1327             }
       
  1328             DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
       
  1329                         env->mmuregs[reg]);
       
  1330         }
       
  1331         break;
       
  1332     case 8: /* User code access, XXX */
       
  1333     case 9: /* Supervisor code access, XXX */
       
  1334     default:
       
  1335         do_unassigned_access(addr, 1, 0, asi, size);
       
  1336         break;
       
  1337     }
       
  1338 #ifdef DEBUG_ASI
       
  1339     dump_asi("write", addr, asi, size, val);
       
  1340 #endif
       
  1341 }
       
  1342 
       
  1343 #endif /* CONFIG_USER_ONLY */
       
  1344 #else /* TARGET_SPARC64 */
       
  1345 
       
  1346 #ifdef CONFIG_USER_ONLY
       
  1347 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
       
  1348 {
       
  1349     uint64_t ret = 0;
       
  1350 #if defined(DEBUG_ASI)
       
  1351     target_ulong last_addr = addr;
       
  1352 #endif
       
  1353 
       
  1354     if (asi < 0x80)
       
  1355         raise_exception(TT_PRIV_ACT);
       
  1356 
       
  1357     helper_check_align(addr, size - 1);
       
  1358     address_mask(env, &addr);
       
  1359 
       
  1360     switch (asi) {
       
  1361     case 0x82: // Primary no-fault
       
  1362     case 0x8a: // Primary no-fault LE
       
  1363         if (page_check_range(addr, size, PAGE_READ) == -1) {
       
  1364 #ifdef DEBUG_ASI
       
  1365             dump_asi("read ", last_addr, asi, size, ret);
       
  1366 #endif
       
  1367             return 0;
       
  1368         }
       
  1369         // Fall through
       
  1370     case 0x80: // Primary
       
  1371     case 0x88: // Primary LE
       
  1372         {
       
  1373             switch(size) {
       
  1374             case 1:
       
  1375                 ret = ldub_raw(addr);
       
  1376                 break;
       
  1377             case 2:
       
  1378                 ret = lduw_raw(addr);
       
  1379                 break;
       
  1380             case 4:
       
  1381                 ret = ldl_raw(addr);
       
  1382                 break;
       
  1383             default:
       
  1384             case 8:
       
  1385                 ret = ldq_raw(addr);
       
  1386                 break;
       
  1387             }
       
  1388         }
       
  1389         break;
       
  1390     case 0x83: // Secondary no-fault
       
  1391     case 0x8b: // Secondary no-fault LE
       
  1392         if (page_check_range(addr, size, PAGE_READ) == -1) {
       
  1393 #ifdef DEBUG_ASI
       
  1394             dump_asi("read ", last_addr, asi, size, ret);
       
  1395 #endif
       
  1396             return 0;
       
  1397         }
       
  1398         // Fall through
       
  1399     case 0x81: // Secondary
       
  1400     case 0x89: // Secondary LE
       
  1401         // XXX
       
  1402         break;
       
  1403     default:
       
  1404         break;
       
  1405     }
       
  1406 
       
  1407     /* Convert from little endian */
       
  1408     switch (asi) {
       
  1409     case 0x88: // Primary LE
       
  1410     case 0x89: // Secondary LE
       
  1411     case 0x8a: // Primary no-fault LE
       
  1412     case 0x8b: // Secondary no-fault LE
       
  1413         switch(size) {
       
  1414         case 2:
       
  1415             ret = bswap16(ret);
       
  1416             break;
       
  1417         case 4:
       
  1418             ret = bswap32(ret);
       
  1419             break;
       
  1420         case 8:
       
  1421             ret = bswap64(ret);
       
  1422             break;
       
  1423         default:
       
  1424             break;
       
  1425         }
       
  1426     default:
       
  1427         break;
       
  1428     }
       
  1429 
       
  1430     /* Convert to signed number */
       
  1431     if (sign) {
       
  1432         switch(size) {
       
  1433         case 1:
       
  1434             ret = (int8_t) ret;
       
  1435             break;
       
  1436         case 2:
       
  1437             ret = (int16_t) ret;
       
  1438             break;
       
  1439         case 4:
       
  1440             ret = (int32_t) ret;
       
  1441             break;
       
  1442         default:
       
  1443             break;
       
  1444         }
       
  1445     }
       
  1446 #ifdef DEBUG_ASI
       
  1447     dump_asi("read ", last_addr, asi, size, ret);
       
  1448 #endif
       
  1449     return ret;
       
  1450 }
       
  1451 
       
  1452 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
       
  1453 {
       
  1454 #ifdef DEBUG_ASI
       
  1455     dump_asi("write", addr, asi, size, val);
       
  1456 #endif
       
  1457     if (asi < 0x80)
       
  1458         raise_exception(TT_PRIV_ACT);
       
  1459 
       
  1460     helper_check_align(addr, size - 1);
       
  1461     address_mask(env, &addr);
       
  1462 
       
  1463     /* Convert to little endian */
       
  1464     switch (asi) {
       
  1465     case 0x88: // Primary LE
       
  1466     case 0x89: // Secondary LE
       
  1467         switch(size) {
       
  1468         case 2:
       
  1469             addr = bswap16(addr);
       
  1470             break;
       
  1471         case 4:
       
  1472             addr = bswap32(addr);
       
  1473             break;
       
  1474         case 8:
       
  1475             addr = bswap64(addr);
       
  1476             break;
       
  1477         default:
       
  1478             break;
       
  1479         }
       
  1480     default:
       
  1481         break;
       
  1482     }
       
  1483 
       
  1484     switch(asi) {
       
  1485     case 0x80: // Primary
       
  1486     case 0x88: // Primary LE
       
  1487         {
       
  1488             switch(size) {
       
  1489             case 1:
       
  1490                 stb_raw(addr, val);
       
  1491                 break;
       
  1492             case 2:
       
  1493                 stw_raw(addr, val);
       
  1494                 break;
       
  1495             case 4:
       
  1496                 stl_raw(addr, val);
       
  1497                 break;
       
  1498             case 8:
       
  1499             default:
       
  1500                 stq_raw(addr, val);
       
  1501                 break;
       
  1502             }
       
  1503         }
       
  1504         break;
       
  1505     case 0x81: // Secondary
       
  1506     case 0x89: // Secondary LE
       
  1507         // XXX
       
  1508         return;
       
  1509 
       
  1510     case 0x82: // Primary no-fault, RO
       
  1511     case 0x83: // Secondary no-fault, RO
       
  1512     case 0x8a: // Primary no-fault LE, RO
       
  1513     case 0x8b: // Secondary no-fault LE, RO
       
  1514     default:
       
  1515         do_unassigned_access(addr, 1, 0, 1, size);
       
  1516         return;
       
  1517     }
       
  1518 }
       
  1519 
       
  1520 #else /* CONFIG_USER_ONLY */
       
  1521 
       
  1522 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
       
  1523 {
       
  1524     uint64_t ret = 0;
       
  1525 #if defined(DEBUG_ASI)
       
  1526     target_ulong last_addr = addr;
       
  1527 #endif
       
  1528 
       
  1529     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
       
  1530         || ((env->def->features & CPU_FEATURE_HYPV)
       
  1531             && asi >= 0x30 && asi < 0x80
       
  1532             && !(env->hpstate & HS_PRIV)))
       
  1533         raise_exception(TT_PRIV_ACT);
       
  1534 
       
  1535     helper_check_align(addr, size - 1);
       
  1536     switch (asi) {
       
  1537     case 0x82: // Primary no-fault
       
  1538     case 0x8a: // Primary no-fault LE
       
  1539         if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
       
  1540 #ifdef DEBUG_ASI
       
  1541             dump_asi("read ", last_addr, asi, size, ret);
       
  1542 #endif
       
  1543             return 0;
       
  1544         }
       
  1545         // Fall through
       
  1546     case 0x10: // As if user primary
       
  1547     case 0x18: // As if user primary LE
       
  1548     case 0x80: // Primary
       
  1549     case 0x88: // Primary LE
       
  1550     case 0xe2: // UA2007 Primary block init
       
  1551     case 0xe3: // UA2007 Secondary block init
       
  1552         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
       
  1553             if ((env->def->features & CPU_FEATURE_HYPV)
       
  1554                 && env->hpstate & HS_PRIV) {
       
  1555                 switch(size) {
       
  1556                 case 1:
       
  1557                     ret = ldub_hypv(addr);
       
  1558                     break;
       
  1559                 case 2:
       
  1560                     ret = lduw_hypv(addr);
       
  1561                     break;
       
  1562                 case 4:
       
  1563                     ret = ldl_hypv(addr);
       
  1564                     break;
       
  1565                 default:
       
  1566                 case 8:
       
  1567                     ret = ldq_hypv(addr);
       
  1568                     break;
       
  1569                 }
       
  1570             } else {
       
  1571                 switch(size) {
       
  1572                 case 1:
       
  1573                     ret = ldub_kernel(addr);
       
  1574                     break;
       
  1575                 case 2:
       
  1576                     ret = lduw_kernel(addr);
       
  1577                     break;
       
  1578                 case 4:
       
  1579                     ret = ldl_kernel(addr);
       
  1580                     break;
       
  1581                 default:
       
  1582                 case 8:
       
  1583                     ret = ldq_kernel(addr);
       
  1584                     break;
       
  1585                 }
       
  1586             }
       
  1587         } else {
       
  1588             switch(size) {
       
  1589             case 1:
       
  1590                 ret = ldub_user(addr);
       
  1591                 break;
       
  1592             case 2:
       
  1593                 ret = lduw_user(addr);
       
  1594                 break;
       
  1595             case 4:
       
  1596                 ret = ldl_user(addr);
       
  1597                 break;
       
  1598             default:
       
  1599             case 8:
       
  1600                 ret = ldq_user(addr);
       
  1601                 break;
       
  1602             }
       
  1603         }
       
  1604         break;
       
  1605     case 0x14: // Bypass
       
  1606     case 0x15: // Bypass, non-cacheable
       
  1607     case 0x1c: // Bypass LE
       
  1608     case 0x1d: // Bypass, non-cacheable LE
       
  1609         {
       
  1610             switch(size) {
       
  1611             case 1:
       
  1612                 ret = ldub_phys(addr);
       
  1613                 break;
       
  1614             case 2:
       
  1615                 ret = lduw_phys(addr);
       
  1616                 break;
       
  1617             case 4:
       
  1618                 ret = ldl_phys(addr);
       
  1619                 break;
       
  1620             default:
       
  1621             case 8:
       
  1622                 ret = ldq_phys(addr);
       
  1623                 break;
       
  1624             }
       
  1625             break;
       
  1626         }
       
  1627     case 0x24: // Nucleus quad LDD 128 bit atomic
       
  1628     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
       
  1629         //  Only ldda allowed
       
  1630         raise_exception(TT_ILL_INSN);
       
  1631         return 0;
       
  1632     case 0x83: // Secondary no-fault
       
  1633     case 0x8b: // Secondary no-fault LE
       
  1634         if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
       
  1635 #ifdef DEBUG_ASI
       
  1636             dump_asi("read ", last_addr, asi, size, ret);
       
  1637 #endif
       
  1638             return 0;
       
  1639         }
       
  1640         // Fall through
       
  1641     case 0x04: // Nucleus
       
  1642     case 0x0c: // Nucleus Little Endian (LE)
       
  1643     case 0x11: // As if user secondary
       
  1644     case 0x19: // As if user secondary LE
       
  1645     case 0x4a: // UPA config
       
  1646     case 0x81: // Secondary
       
  1647     case 0x89: // Secondary LE
       
  1648         // XXX
       
  1649         break;
       
  1650     case 0x45: // LSU
       
  1651         ret = env->lsu;
       
  1652         break;
       
  1653     case 0x50: // I-MMU regs
       
  1654         {
       
  1655             int reg = (addr >> 3) & 0xf;
       
  1656 
       
  1657             ret = env->immuregs[reg];
       
  1658             break;
       
  1659         }
       
  1660     case 0x51: // I-MMU 8k TSB pointer
       
  1661     case 0x52: // I-MMU 64k TSB pointer
       
  1662         // XXX
       
  1663         break;
       
  1664     case 0x55: // I-MMU data access
       
  1665         {
       
  1666             int reg = (addr >> 3) & 0x3f;
       
  1667 
       
  1668             ret = env->itlb_tte[reg];
       
  1669             break;
       
  1670         }
       
  1671     case 0x56: // I-MMU tag read
       
  1672         {
       
  1673             int reg = (addr >> 3) & 0x3f;
       
  1674 
       
  1675             ret = env->itlb_tag[reg];
       
  1676             break;
       
  1677         }
       
  1678     case 0x58: // D-MMU regs
       
  1679         {
       
  1680             int reg = (addr >> 3) & 0xf;
       
  1681 
       
  1682             ret = env->dmmuregs[reg];
       
  1683             break;
       
  1684         }
       
  1685     case 0x5d: // D-MMU data access
       
  1686         {
       
  1687             int reg = (addr >> 3) & 0x3f;
       
  1688 
       
  1689             ret = env->dtlb_tte[reg];
       
  1690             break;
       
  1691         }
       
  1692     case 0x5e: // D-MMU tag read
       
  1693         {
       
  1694             int reg = (addr >> 3) & 0x3f;
       
  1695 
       
  1696             ret = env->dtlb_tag[reg];
       
  1697             break;
       
  1698         }
       
  1699     case 0x46: // D-cache data
       
  1700     case 0x47: // D-cache tag access
       
  1701     case 0x4b: // E-cache error enable
       
  1702     case 0x4c: // E-cache asynchronous fault status
       
  1703     case 0x4d: // E-cache asynchronous fault address
       
  1704     case 0x4e: // E-cache tag data
       
  1705     case 0x66: // I-cache instruction access
       
  1706     case 0x67: // I-cache tag access
       
  1707     case 0x6e: // I-cache predecode
       
  1708     case 0x6f: // I-cache LRU etc.
       
  1709     case 0x76: // E-cache tag
       
  1710     case 0x7e: // E-cache tag
       
  1711         break;
       
  1712     case 0x59: // D-MMU 8k TSB pointer
       
  1713     case 0x5a: // D-MMU 64k TSB pointer
       
  1714     case 0x5b: // D-MMU data pointer
       
  1715     case 0x48: // Interrupt dispatch, RO
       
  1716     case 0x49: // Interrupt data receive
       
  1717     case 0x7f: // Incoming interrupt vector, RO
       
  1718         // XXX
       
  1719         break;
       
  1720     case 0x54: // I-MMU data in, WO
       
  1721     case 0x57: // I-MMU demap, WO
       
  1722     case 0x5c: // D-MMU data in, WO
       
  1723     case 0x5f: // D-MMU demap, WO
       
  1724     case 0x77: // Interrupt vector, WO
       
  1725     default:
       
  1726         do_unassigned_access(addr, 0, 0, 1, size);
       
  1727         ret = 0;
       
  1728         break;
       
  1729     }
       
  1730 
       
  1731     /* Convert from little endian */
       
  1732     switch (asi) {
       
  1733     case 0x0c: // Nucleus Little Endian (LE)
       
  1734     case 0x18: // As if user primary LE
       
  1735     case 0x19: // As if user secondary LE
       
  1736     case 0x1c: // Bypass LE
       
  1737     case 0x1d: // Bypass, non-cacheable LE
       
  1738     case 0x88: // Primary LE
       
  1739     case 0x89: // Secondary LE
       
  1740     case 0x8a: // Primary no-fault LE
       
  1741     case 0x8b: // Secondary no-fault LE
       
  1742         switch(size) {
       
  1743         case 2:
       
  1744             ret = bswap16(ret);
       
  1745             break;
       
  1746         case 4:
       
  1747             ret = bswap32(ret);
       
  1748             break;
       
  1749         case 8:
       
  1750             ret = bswap64(ret);
       
  1751             break;
       
  1752         default:
       
  1753             break;
       
  1754         }
       
  1755     default:
       
  1756         break;
       
  1757     }
       
  1758 
       
  1759     /* Convert to signed number */
       
  1760     if (sign) {
       
  1761         switch(size) {
       
  1762         case 1:
       
  1763             ret = (int8_t) ret;
       
  1764             break;
       
  1765         case 2:
       
  1766             ret = (int16_t) ret;
       
  1767             break;
       
  1768         case 4:
       
  1769             ret = (int32_t) ret;
       
  1770             break;
       
  1771         default:
       
  1772             break;
       
  1773         }
       
  1774     }
       
  1775 #ifdef DEBUG_ASI
       
  1776     dump_asi("read ", last_addr, asi, size, ret);
       
  1777 #endif
       
  1778     return ret;
       
  1779 }
       
  1780 
       
  1781 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
       
  1782 {
       
  1783 #ifdef DEBUG_ASI
       
  1784     dump_asi("write", addr, asi, size, val);
       
  1785 #endif
       
  1786     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
       
  1787         || ((env->def->features & CPU_FEATURE_HYPV)
       
  1788             && asi >= 0x30 && asi < 0x80
       
  1789             && !(env->hpstate & HS_PRIV)))
       
  1790         raise_exception(TT_PRIV_ACT);
       
  1791 
       
  1792     helper_check_align(addr, size - 1);
       
  1793     /* Convert to little endian */
       
  1794     switch (asi) {
       
  1795     case 0x0c: // Nucleus Little Endian (LE)
       
  1796     case 0x18: // As if user primary LE
       
  1797     case 0x19: // As if user secondary LE
       
  1798     case 0x1c: // Bypass LE
       
  1799     case 0x1d: // Bypass, non-cacheable LE
       
  1800     case 0x88: // Primary LE
       
  1801     case 0x89: // Secondary LE
       
  1802         switch(size) {
       
  1803         case 2:
       
  1804             addr = bswap16(addr);
       
  1805             break;
       
  1806         case 4:
       
  1807             addr = bswap32(addr);
       
  1808             break;
       
  1809         case 8:
       
  1810             addr = bswap64(addr);
       
  1811             break;
       
  1812         default:
       
  1813             break;
       
  1814         }
       
  1815     default:
       
  1816         break;
       
  1817     }
       
  1818 
       
  1819     switch(asi) {
       
  1820     case 0x10: // As if user primary
       
  1821     case 0x18: // As if user primary LE
       
  1822     case 0x80: // Primary
       
  1823     case 0x88: // Primary LE
       
  1824     case 0xe2: // UA2007 Primary block init
       
  1825     case 0xe3: // UA2007 Secondary block init
       
  1826         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
       
  1827             if ((env->def->features & CPU_FEATURE_HYPV)
       
  1828                 && env->hpstate & HS_PRIV) {
       
  1829                 switch(size) {
       
  1830                 case 1:
       
  1831                     stb_hypv(addr, val);
       
  1832                     break;
       
  1833                 case 2:
       
  1834                     stw_hypv(addr, val);
       
  1835                     break;
       
  1836                 case 4:
       
  1837                     stl_hypv(addr, val);
       
  1838                     break;
       
  1839                 case 8:
       
  1840                 default:
       
  1841                     stq_hypv(addr, val);
       
  1842                     break;
       
  1843                 }
       
  1844             } else {
       
  1845                 switch(size) {
       
  1846                 case 1:
       
  1847                     stb_kernel(addr, val);
       
  1848                     break;
       
  1849                 case 2:
       
  1850                     stw_kernel(addr, val);
       
  1851                     break;
       
  1852                 case 4:
       
  1853                     stl_kernel(addr, val);
       
  1854                     break;
       
  1855                 case 8:
       
  1856                 default:
       
  1857                     stq_kernel(addr, val);
       
  1858                     break;
       
  1859                 }
       
  1860             }
       
  1861         } else {
       
  1862             switch(size) {
       
  1863             case 1:
       
  1864                 stb_user(addr, val);
       
  1865                 break;
       
  1866             case 2:
       
  1867                 stw_user(addr, val);
       
  1868                 break;
       
  1869             case 4:
       
  1870                 stl_user(addr, val);
       
  1871                 break;
       
  1872             case 8:
       
  1873             default:
       
  1874                 stq_user(addr, val);
       
  1875                 break;
       
  1876             }
       
  1877         }
       
  1878         break;
       
  1879     case 0x14: // Bypass
       
  1880     case 0x15: // Bypass, non-cacheable
       
  1881     case 0x1c: // Bypass LE
       
  1882     case 0x1d: // Bypass, non-cacheable LE
       
  1883         {
       
  1884             switch(size) {
       
  1885             case 1:
       
  1886                 stb_phys(addr, val);
       
  1887                 break;
       
  1888             case 2:
       
  1889                 stw_phys(addr, val);
       
  1890                 break;
       
  1891             case 4:
       
  1892                 stl_phys(addr, val);
       
  1893                 break;
       
  1894             case 8:
       
  1895             default:
       
  1896                 stq_phys(addr, val);
       
  1897                 break;
       
  1898             }
       
  1899         }
       
  1900         return;
       
  1901     case 0x24: // Nucleus quad LDD 128 bit atomic
       
  1902     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
       
  1903         //  Only ldda allowed
       
  1904         raise_exception(TT_ILL_INSN);
       
  1905         return;
       
  1906     case 0x04: // Nucleus
       
  1907     case 0x0c: // Nucleus Little Endian (LE)
       
  1908     case 0x11: // As if user secondary
       
  1909     case 0x19: // As if user secondary LE
       
  1910     case 0x4a: // UPA config
       
  1911     case 0x81: // Secondary
       
  1912     case 0x89: // Secondary LE
       
  1913         // XXX
       
  1914         return;
       
  1915     case 0x45: // LSU
       
  1916         {
       
  1917             uint64_t oldreg;
       
  1918 
       
  1919             oldreg = env->lsu;
       
  1920             env->lsu = val & (DMMU_E | IMMU_E);
       
  1921             // Mappings generated during D/I MMU disabled mode are
       
  1922             // invalid in normal mode
       
  1923             if (oldreg != env->lsu) {
       
  1924                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
       
  1925                             oldreg, env->lsu);
       
  1926 #ifdef DEBUG_MMU
       
  1927                 dump_mmu(env);
       
  1928 #endif
       
  1929                 tlb_flush(env, 1);
       
  1930             }
       
  1931             return;
       
  1932         }
       
  1933     case 0x50: // I-MMU regs
       
  1934         {
       
  1935             int reg = (addr >> 3) & 0xf;
       
  1936             uint64_t oldreg;
       
  1937 
       
  1938             oldreg = env->immuregs[reg];
       
  1939             switch(reg) {
       
  1940             case 0: // RO
       
  1941             case 4:
       
  1942                 return;
       
  1943             case 1: // Not in I-MMU
       
  1944             case 2:
       
  1945             case 7:
       
  1946             case 8:
       
  1947                 return;
       
  1948             case 3: // SFSR
       
  1949                 if ((val & 1) == 0)
       
  1950                     val = 0; // Clear SFSR
       
  1951                 break;
       
  1952             case 5: // TSB access
       
  1953             case 6: // Tag access
       
  1954             default:
       
  1955                 break;
       
  1956             }
       
  1957             env->immuregs[reg] = val;
       
  1958             if (oldreg != env->immuregs[reg]) {
       
  1959                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
       
  1960                             PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
       
  1961             }
       
  1962 #ifdef DEBUG_MMU
       
  1963             dump_mmu(env);
       
  1964 #endif
       
  1965             return;
       
  1966         }
       
  1967     case 0x54: // I-MMU data in
       
  1968         {
       
  1969             unsigned int i;
       
  1970 
       
  1971             // Try finding an invalid entry
       
  1972             for (i = 0; i < 64; i++) {
       
  1973                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
       
  1974                     env->itlb_tag[i] = env->immuregs[6];
       
  1975                     env->itlb_tte[i] = val;
       
  1976                     return;
       
  1977                 }
       
  1978             }
       
  1979             // Try finding an unlocked entry
       
  1980             for (i = 0; i < 64; i++) {
       
  1981                 if ((env->itlb_tte[i] & 0x40) == 0) {
       
  1982                     env->itlb_tag[i] = env->immuregs[6];
       
  1983                     env->itlb_tte[i] = val;
       
  1984                     return;
       
  1985                 }
       
  1986             }
       
  1987             // error state?
       
  1988             return;
       
  1989         }
       
  1990     case 0x55: // I-MMU data access
       
  1991         {
       
  1992             // TODO: auto demap
       
  1993 
       
  1994             unsigned int i = (addr >> 3) & 0x3f;
       
  1995 
       
  1996             env->itlb_tag[i] = env->immuregs[6];
       
  1997             env->itlb_tte[i] = val;
       
  1998             return;
       
  1999         }
       
  2000     case 0x57: // I-MMU demap
       
  2001         {
       
  2002             unsigned int i;
       
  2003 
       
  2004             for (i = 0; i < 64; i++) {
       
  2005                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
       
  2006                     target_ulong mask = 0xffffffffffffe000ULL;
       
  2007 
       
  2008                     mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
       
  2009                     if ((val & mask) == (env->itlb_tag[i] & mask)) {
       
  2010                         env->itlb_tag[i] = 0;
       
  2011                         env->itlb_tte[i] = 0;
       
  2012                     }
       
  2013                     return;
       
  2014                 }
       
  2015             }
       
  2016         }
       
  2017         return;
       
  2018     case 0x58: // D-MMU regs
       
  2019         {
       
  2020             int reg = (addr >> 3) & 0xf;
       
  2021             uint64_t oldreg;
       
  2022 
       
  2023             oldreg = env->dmmuregs[reg];
       
  2024             switch(reg) {
       
  2025             case 0: // RO
       
  2026             case 4:
       
  2027                 return;
       
  2028             case 3: // SFSR
       
  2029                 if ((val & 1) == 0) {
       
  2030                     val = 0; // Clear SFSR, Fault address
       
  2031                     env->dmmuregs[4] = 0;
       
  2032                 }
       
  2033                 env->dmmuregs[reg] = val;
       
  2034                 break;
       
  2035             case 1: // Primary context
       
  2036             case 2: // Secondary context
       
  2037             case 5: // TSB access
       
  2038             case 6: // Tag access
       
  2039             case 7: // Virtual Watchpoint
       
  2040             case 8: // Physical Watchpoint
       
  2041             default:
       
  2042                 break;
       
  2043             }
       
  2044             env->dmmuregs[reg] = val;
       
  2045             if (oldreg != env->dmmuregs[reg]) {
       
  2046                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
       
  2047                             PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
       
  2048             }
       
  2049 #ifdef DEBUG_MMU
       
  2050             dump_mmu(env);
       
  2051 #endif
       
  2052             return;
       
  2053         }
       
  2054     case 0x5c: // D-MMU data in
       
  2055         {
       
  2056             unsigned int i;
       
  2057 
       
  2058             // Try finding an invalid entry
       
  2059             for (i = 0; i < 64; i++) {
       
  2060                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
       
  2061                     env->dtlb_tag[i] = env->dmmuregs[6];
       
  2062                     env->dtlb_tte[i] = val;
       
  2063                     return;
       
  2064                 }
       
  2065             }
       
  2066             // Try finding an unlocked entry
       
  2067             for (i = 0; i < 64; i++) {
       
  2068                 if ((env->dtlb_tte[i] & 0x40) == 0) {
       
  2069                     env->dtlb_tag[i] = env->dmmuregs[6];
       
  2070                     env->dtlb_tte[i] = val;
       
  2071                     return;
       
  2072                 }
       
  2073             }
       
  2074             // error state?
       
  2075             return;
       
  2076         }
       
  2077     case 0x5d: // D-MMU data access
       
  2078         {
       
  2079             unsigned int i = (addr >> 3) & 0x3f;
       
  2080 
       
  2081             env->dtlb_tag[i] = env->dmmuregs[6];
       
  2082             env->dtlb_tte[i] = val;
       
  2083             return;
       
  2084         }
       
  2085     case 0x5f: // D-MMU demap
       
  2086         {
       
  2087             unsigned int i;
       
  2088 
       
  2089             for (i = 0; i < 64; i++) {
       
  2090                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
       
  2091                     target_ulong mask = 0xffffffffffffe000ULL;
       
  2092 
       
  2093                     mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
       
  2094                     if ((val & mask) == (env->dtlb_tag[i] & mask)) {
       
  2095                         env->dtlb_tag[i] = 0;
       
  2096                         env->dtlb_tte[i] = 0;
       
  2097                     }
       
  2098                     return;
       
  2099                 }
       
  2100             }
       
  2101         }
       
  2102         return;
       
  2103     case 0x49: // Interrupt data receive
       
  2104         // XXX
       
  2105         return;
       
  2106     case 0x46: // D-cache data
       
  2107     case 0x47: // D-cache tag access
       
  2108     case 0x4b: // E-cache error enable
       
  2109     case 0x4c: // E-cache asynchronous fault status
       
  2110     case 0x4d: // E-cache asynchronous fault address
       
  2111     case 0x4e: // E-cache tag data
       
  2112     case 0x66: // I-cache instruction access
       
  2113     case 0x67: // I-cache tag access
       
  2114     case 0x6e: // I-cache predecode
       
  2115     case 0x6f: // I-cache LRU etc.
       
  2116     case 0x76: // E-cache tag
       
  2117     case 0x7e: // E-cache tag
       
  2118         return;
       
  2119     case 0x51: // I-MMU 8k TSB pointer, RO
       
  2120     case 0x52: // I-MMU 64k TSB pointer, RO
       
  2121     case 0x56: // I-MMU tag read, RO
       
  2122     case 0x59: // D-MMU 8k TSB pointer, RO
       
  2123     case 0x5a: // D-MMU 64k TSB pointer, RO
       
  2124     case 0x5b: // D-MMU data pointer, RO
       
  2125     case 0x5e: // D-MMU tag read, RO
       
  2126     case 0x48: // Interrupt dispatch, RO
       
  2127     case 0x7f: // Incoming interrupt vector, RO
       
  2128     case 0x82: // Primary no-fault, RO
       
  2129     case 0x83: // Secondary no-fault, RO
       
  2130     case 0x8a: // Primary no-fault LE, RO
       
  2131     case 0x8b: // Secondary no-fault LE, RO
       
  2132     default:
       
  2133         do_unassigned_access(addr, 1, 0, 1, size);
       
  2134         return;
       
  2135     }
       
  2136 }
       
  2137 #endif /* CONFIG_USER_ONLY */
       
  2138 
       
  2139 void helper_ldda_asi(target_ulong addr, int asi, int rd)
       
  2140 {
       
  2141     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
       
  2142         || ((env->def->features & CPU_FEATURE_HYPV)
       
  2143             && asi >= 0x30 && asi < 0x80
       
  2144             && !(env->hpstate & HS_PRIV)))
       
  2145         raise_exception(TT_PRIV_ACT);
       
  2146 
       
  2147     switch (asi) {
       
  2148     case 0x24: // Nucleus quad LDD 128 bit atomic
       
  2149     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
       
  2150         helper_check_align(addr, 0xf);
       
  2151         if (rd == 0) {
       
  2152             env->gregs[1] = ldq_kernel(addr + 8);
       
  2153             if (asi == 0x2c)
       
  2154                 bswap64s(&env->gregs[1]);
       
  2155         } else if (rd < 8) {
       
  2156             env->gregs[rd] = ldq_kernel(addr);
       
  2157             env->gregs[rd + 1] = ldq_kernel(addr + 8);
       
  2158             if (asi == 0x2c) {
       
  2159                 bswap64s(&env->gregs[rd]);
       
  2160                 bswap64s(&env->gregs[rd + 1]);
       
  2161             }
       
  2162         } else {
       
  2163             env->regwptr[rd] = ldq_kernel(addr);
       
  2164             env->regwptr[rd + 1] = ldq_kernel(addr + 8);
       
  2165             if (asi == 0x2c) {
       
  2166                 bswap64s(&env->regwptr[rd]);
       
  2167                 bswap64s(&env->regwptr[rd + 1]);
       
  2168             }
       
  2169         }
       
  2170         break;
       
  2171     default:
       
  2172         helper_check_align(addr, 0x3);
       
  2173         if (rd == 0)
       
  2174             env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
       
  2175         else if (rd < 8) {
       
  2176             env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
       
  2177             env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
       
  2178         } else {
       
  2179             env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
       
  2180             env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
       
  2181         }
       
  2182         break;
       
  2183     }
       
  2184 }
       
  2185 
       
  2186 void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
       
  2187 {
       
  2188     unsigned int i;
       
  2189     target_ulong val;
       
  2190 
       
  2191     helper_check_align(addr, 3);
       
  2192     switch (asi) {
       
  2193     case 0xf0: // Block load primary
       
  2194     case 0xf1: // Block load secondary
       
  2195     case 0xf8: // Block load primary LE
       
  2196     case 0xf9: // Block load secondary LE
       
  2197         if (rd & 7) {
       
  2198             raise_exception(TT_ILL_INSN);
       
  2199             return;
       
  2200         }
       
  2201         helper_check_align(addr, 0x3f);
       
  2202         for (i = 0; i < 16; i++) {
       
  2203             *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
       
  2204                                                          0);
       
  2205             addr += 4;
       
  2206         }
       
  2207 
       
  2208         return;
       
  2209     default:
       
  2210         break;
       
  2211     }
       
  2212 
       
  2213     val = helper_ld_asi(addr, asi, size, 0);
       
  2214     switch(size) {
       
  2215     default:
       
  2216     case 4:
       
  2217         *((uint32_t *)&env->fpr[rd]) = val;
       
  2218         break;
       
  2219     case 8:
       
  2220         *((int64_t *)&DT0) = val;
       
  2221         break;
       
  2222     case 16:
       
  2223         // XXX
       
  2224         break;
       
  2225     }
       
  2226 }
       
  2227 
       
  2228 void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
       
  2229 {
       
  2230     unsigned int i;
       
  2231     target_ulong val = 0;
       
  2232 
       
  2233     helper_check_align(addr, 3);
       
  2234     switch (asi) {
       
  2235     case 0xe0: // UA2007 Block commit store primary (cache flush)
       
  2236     case 0xe1: // UA2007 Block commit store secondary (cache flush)
       
  2237     case 0xf0: // Block store primary
       
  2238     case 0xf1: // Block store secondary
       
  2239     case 0xf8: // Block store primary LE
       
  2240     case 0xf9: // Block store secondary LE
       
  2241         if (rd & 7) {
       
  2242             raise_exception(TT_ILL_INSN);
       
  2243             return;
       
  2244         }
       
  2245         helper_check_align(addr, 0x3f);
       
  2246         for (i = 0; i < 16; i++) {
       
  2247             val = *(uint32_t *)&env->fpr[rd++];
       
  2248             helper_st_asi(addr, val, asi & 0x8f, 4);
       
  2249             addr += 4;
       
  2250         }
       
  2251 
       
  2252         return;
       
  2253     default:
       
  2254         break;
       
  2255     }
       
  2256 
       
  2257     switch(size) {
       
  2258     default:
       
  2259     case 4:
       
  2260         val = *((uint32_t *)&env->fpr[rd]);
       
  2261         break;
       
  2262     case 8:
       
  2263         val = *((int64_t *)&DT0);
       
  2264         break;
       
  2265     case 16:
       
  2266         // XXX
       
  2267         break;
       
  2268     }
       
  2269     helper_st_asi(addr, val, asi, size);
       
  2270 }
       
  2271 
       
  2272 target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
       
  2273                             target_ulong val2, uint32_t asi)
       
  2274 {
       
  2275     target_ulong ret;
       
  2276 
       
  2277     val2 &= 0xffffffffUL;
       
  2278     ret = helper_ld_asi(addr, asi, 4, 0);
       
  2279     ret &= 0xffffffffUL;
       
  2280     if (val2 == ret)
       
  2281         helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
       
  2282     return ret;
       
  2283 }
       
  2284 
       
  2285 target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
       
  2286                              target_ulong val2, uint32_t asi)
       
  2287 {
       
  2288     target_ulong ret;
       
  2289 
       
  2290     ret = helper_ld_asi(addr, asi, 8, 0);
       
  2291     if (val2 == ret)
       
  2292         helper_st_asi(addr, val1, asi, 8);
       
  2293     return ret;
       
  2294 }
       
  2295 #endif /* TARGET_SPARC64 */
       
  2296 
       
  2297 #ifndef TARGET_SPARC64
       
  2298 void helper_rett(void)
       
  2299 {
       
  2300     unsigned int cwp;
       
  2301 
       
  2302     if (env->psret == 1)
       
  2303         raise_exception(TT_ILL_INSN);
       
  2304 
       
  2305     env->psret = 1;
       
  2306     cwp = cpu_cwp_inc(env, env->cwp + 1) ;
       
  2307     if (env->wim & (1 << cwp)) {
       
  2308         raise_exception(TT_WIN_UNF);
       
  2309     }
       
  2310     set_cwp(cwp);
       
  2311     env->psrs = env->psrps;
       
  2312 }
       
  2313 #endif
       
  2314 
       
  2315 target_ulong helper_udiv(target_ulong a, target_ulong b)
       
  2316 {
       
  2317     uint64_t x0;
       
  2318     uint32_t x1;
       
  2319 
       
  2320     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
       
  2321     x1 = b;
       
  2322 
       
  2323     if (x1 == 0) {
       
  2324         raise_exception(TT_DIV_ZERO);
       
  2325     }
       
  2326 
       
  2327     x0 = x0 / x1;
       
  2328     if (x0 > 0xffffffff) {
       
  2329         env->cc_src2 = 1;
       
  2330         return 0xffffffff;
       
  2331     } else {
       
  2332         env->cc_src2 = 0;
       
  2333         return x0;
       
  2334     }
       
  2335 }
       
  2336 
       
  2337 target_ulong helper_sdiv(target_ulong a, target_ulong b)
       
  2338 {
       
  2339     int64_t x0;
       
  2340     int32_t x1;
       
  2341 
       
  2342     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
       
  2343     x1 = b;
       
  2344 
       
  2345     if (x1 == 0) {
       
  2346         raise_exception(TT_DIV_ZERO);
       
  2347     }
       
  2348 
       
  2349     x0 = x0 / x1;
       
  2350     if ((int32_t) x0 != x0) {
       
  2351         env->cc_src2 = 1;
       
  2352         return x0 < 0? 0x80000000: 0x7fffffff;
       
  2353     } else {
       
  2354         env->cc_src2 = 0;
       
  2355         return x0;
       
  2356     }
       
  2357 }
       
  2358 
       
  2359 void helper_stdf(target_ulong addr, int mem_idx)
       
  2360 {
       
  2361     helper_check_align(addr, 7);
       
  2362 #if !defined(CONFIG_USER_ONLY)
       
  2363     switch (mem_idx) {
       
  2364     case 0:
       
  2365         stfq_user(addr, DT0);
       
  2366         break;
       
  2367     case 1:
       
  2368         stfq_kernel(addr, DT0);
       
  2369         break;
       
  2370 #ifdef TARGET_SPARC64
       
  2371     case 2:
       
  2372         stfq_hypv(addr, DT0);
       
  2373         break;
       
  2374 #endif
       
  2375     default:
       
  2376         break;
       
  2377     }
       
  2378 #else
       
  2379     address_mask(env, &addr);
       
  2380     stfq_raw(addr, DT0);
       
  2381 #endif
       
  2382 }
       
  2383 
       
  2384 void helper_lddf(target_ulong addr, int mem_idx)
       
  2385 {
       
  2386     helper_check_align(addr, 7);
       
  2387 #if !defined(CONFIG_USER_ONLY)
       
  2388     switch (mem_idx) {
       
  2389     case 0:
       
  2390         DT0 = ldfq_user(addr);
       
  2391         break;
       
  2392     case 1:
       
  2393         DT0 = ldfq_kernel(addr);
       
  2394         break;
       
  2395 #ifdef TARGET_SPARC64
       
  2396     case 2:
       
  2397         DT0 = ldfq_hypv(addr);
       
  2398         break;
       
  2399 #endif
       
  2400     default:
       
  2401         break;
       
  2402     }
       
  2403 #else
       
  2404     address_mask(env, &addr);
       
  2405     DT0 = ldfq_raw(addr);
       
  2406 #endif
       
  2407 }
       
  2408 
       
  2409 void helper_ldqf(target_ulong addr, int mem_idx)
       
  2410 {
       
  2411     // XXX add 128 bit load
       
  2412     CPU_QuadU u;
       
  2413 
       
  2414     helper_check_align(addr, 7);
       
  2415 #if !defined(CONFIG_USER_ONLY)
       
  2416     switch (mem_idx) {
       
  2417     case 0:
       
  2418         u.ll.upper = ldq_user(addr);
       
  2419         u.ll.lower = ldq_user(addr + 8);
       
  2420         QT0 = u.q;
       
  2421         break;
       
  2422     case 1:
       
  2423         u.ll.upper = ldq_kernel(addr);
       
  2424         u.ll.lower = ldq_kernel(addr + 8);
       
  2425         QT0 = u.q;
       
  2426         break;
       
  2427 #ifdef TARGET_SPARC64
       
  2428     case 2:
       
  2429         u.ll.upper = ldq_hypv(addr);
       
  2430         u.ll.lower = ldq_hypv(addr + 8);
       
  2431         QT0 = u.q;
       
  2432         break;
       
  2433 #endif
       
  2434     default:
       
  2435         break;
       
  2436     }
       
  2437 #else
       
  2438     address_mask(env, &addr);
       
  2439     u.ll.upper = ldq_raw(addr);
       
  2440     u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
       
  2441     QT0 = u.q;
       
  2442 #endif
       
  2443 }
       
  2444 
       
  2445 void helper_stqf(target_ulong addr, int mem_idx)
       
  2446 {
       
  2447     // XXX add 128 bit store
       
  2448     CPU_QuadU u;
       
  2449 
       
  2450     helper_check_align(addr, 7);
       
  2451 #if !defined(CONFIG_USER_ONLY)
       
  2452     switch (mem_idx) {
       
  2453     case 0:
       
  2454         u.q = QT0;
       
  2455         stq_user(addr, u.ll.upper);
       
  2456         stq_user(addr + 8, u.ll.lower);
       
  2457         break;
       
  2458     case 1:
       
  2459         u.q = QT0;
       
  2460         stq_kernel(addr, u.ll.upper);
       
  2461         stq_kernel(addr + 8, u.ll.lower);
       
  2462         break;
       
  2463 #ifdef TARGET_SPARC64
       
  2464     case 2:
       
  2465         u.q = QT0;
       
  2466         stq_hypv(addr, u.ll.upper);
       
  2467         stq_hypv(addr + 8, u.ll.lower);
       
  2468         break;
       
  2469 #endif
       
  2470     default:
       
  2471         break;
       
  2472     }
       
  2473 #else
       
  2474     u.q = QT0;
       
  2475     address_mask(env, &addr);
       
  2476     stq_raw(addr, u.ll.upper);
       
  2477     stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
       
  2478 #endif
       
  2479 }
       
  2480 
       
  2481 static inline void set_fsr(void)
       
  2482 {
       
  2483     int rnd_mode;
       
  2484 
       
  2485     switch (env->fsr & FSR_RD_MASK) {
       
  2486     case FSR_RD_NEAREST:
       
  2487         rnd_mode = float_round_nearest_even;
       
  2488         break;
       
  2489     default:
       
  2490     case FSR_RD_ZERO:
       
  2491         rnd_mode = float_round_to_zero;
       
  2492         break;
       
  2493     case FSR_RD_POS:
       
  2494         rnd_mode = float_round_up;
       
  2495         break;
       
  2496     case FSR_RD_NEG:
       
  2497         rnd_mode = float_round_down;
       
  2498         break;
       
  2499     }
       
  2500     set_float_rounding_mode(rnd_mode, &env->fp_status);
       
  2501 }
       
  2502 
       
  2503 void helper_ldfsr(uint32_t new_fsr)
       
  2504 {
       
  2505     env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
       
  2506     set_fsr();
       
  2507 }
       
  2508 
       
  2509 #ifdef TARGET_SPARC64
       
  2510 void helper_ldxfsr(uint64_t new_fsr)
       
  2511 {
       
  2512     env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
       
  2513     set_fsr();
       
  2514 }
       
  2515 #endif
       
  2516 
       
  2517 void helper_debug(void)
       
  2518 {
       
  2519     env->exception_index = EXCP_DEBUG;
       
  2520     cpu_loop_exit();
       
  2521 }
       
  2522 
       
  2523 #ifndef TARGET_SPARC64
       
  2524 /* XXX: use another pointer for %iN registers to avoid slow wrapping
       
  2525    handling ? */
       
  2526 void helper_save(void)
       
  2527 {
       
  2528     uint32_t cwp;
       
  2529 
       
  2530     cwp = cpu_cwp_dec(env, env->cwp - 1);
       
  2531     if (env->wim & (1 << cwp)) {
       
  2532         raise_exception(TT_WIN_OVF);
       
  2533     }
       
  2534     set_cwp(cwp);
       
  2535 }
       
  2536 
       
  2537 void helper_restore(void)
       
  2538 {
       
  2539     uint32_t cwp;
       
  2540 
       
  2541     cwp = cpu_cwp_inc(env, env->cwp + 1);
       
  2542     if (env->wim & (1 << cwp)) {
       
  2543         raise_exception(TT_WIN_UNF);
       
  2544     }
       
  2545     set_cwp(cwp);
       
  2546 }
       
  2547 
       
  2548 void helper_wrpsr(target_ulong new_psr)
       
  2549 {
       
  2550     if ((new_psr & PSR_CWP) >= env->nwindows)
       
  2551         raise_exception(TT_ILL_INSN);
       
  2552     else
       
  2553         PUT_PSR(env, new_psr);
       
  2554 }
       
  2555 
       
  2556 target_ulong helper_rdpsr(void)
       
  2557 {
       
  2558     return GET_PSR(env);
       
  2559 }
       
  2560 
       
  2561 #else
       
  2562 /* XXX: use another pointer for %iN registers to avoid slow wrapping
       
  2563    handling ? */
       
  2564 void helper_save(void)
       
  2565 {
       
  2566     uint32_t cwp;
       
  2567 
       
  2568     cwp = cpu_cwp_dec(env, env->cwp - 1);
       
  2569     if (env->cansave == 0) {
       
  2570         raise_exception(TT_SPILL | (env->otherwin != 0 ?
       
  2571                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
       
  2572                                     ((env->wstate & 0x7) << 2)));
       
  2573     } else {
       
  2574         if (env->cleanwin - env->canrestore == 0) {
       
  2575             // XXX Clean windows without trap
       
  2576             raise_exception(TT_CLRWIN);
       
  2577         } else {
       
  2578             env->cansave--;
       
  2579             env->canrestore++;
       
  2580             set_cwp(cwp);
       
  2581         }
       
  2582     }
       
  2583 }
       
  2584 
       
  2585 void helper_restore(void)
       
  2586 {
       
  2587     uint32_t cwp;
       
  2588 
       
  2589     cwp = cpu_cwp_inc(env, env->cwp + 1);
       
  2590     if (env->canrestore == 0) {
       
  2591         raise_exception(TT_FILL | (env->otherwin != 0 ?
       
  2592                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
       
  2593                                    ((env->wstate & 0x7) << 2)));
       
  2594     } else {
       
  2595         env->cansave++;
       
  2596         env->canrestore--;
       
  2597         set_cwp(cwp);
       
  2598     }
       
  2599 }
       
  2600 
       
  2601 void helper_flushw(void)
       
  2602 {
       
  2603     if (env->cansave != env->nwindows - 2) {
       
  2604         raise_exception(TT_SPILL | (env->otherwin != 0 ?
       
  2605                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
       
  2606                                     ((env->wstate & 0x7) << 2)));
       
  2607     }
       
  2608 }
       
  2609 
       
  2610 void helper_saved(void)
       
  2611 {
       
  2612     env->cansave++;
       
  2613     if (env->otherwin == 0)
       
  2614         env->canrestore--;
       
  2615     else
       
  2616         env->otherwin--;
       
  2617 }
       
  2618 
       
  2619 void helper_restored(void)
       
  2620 {
       
  2621     env->canrestore++;
       
  2622     if (env->cleanwin < env->nwindows - 1)
       
  2623         env->cleanwin++;
       
  2624     if (env->otherwin == 0)
       
  2625         env->cansave--;
       
  2626     else
       
  2627         env->otherwin--;
       
  2628 }
       
  2629 
       
  2630 target_ulong helper_rdccr(void)
       
  2631 {
       
  2632     return GET_CCR(env);
       
  2633 }
       
  2634 
       
  2635 void helper_wrccr(target_ulong new_ccr)
       
  2636 {
       
  2637     PUT_CCR(env, new_ccr);
       
  2638 }
       
  2639 
       
  2640 // CWP handling is reversed in V9, but we still use the V8 register
       
  2641 // order.
       
  2642 target_ulong helper_rdcwp(void)
       
  2643 {
       
  2644     return GET_CWP64(env);
       
  2645 }
       
  2646 
       
  2647 void helper_wrcwp(target_ulong new_cwp)
       
  2648 {
       
  2649     PUT_CWP64(env, new_cwp);
       
  2650 }
       
  2651 
       
  2652 // This function uses non-native bit order
       
  2653 #define GET_FIELD(X, FROM, TO)                                  \
       
  2654     ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
       
  2655 
       
  2656 // This function uses the order in the manuals, i.e. bit 0 is 2^0
       
  2657 #define GET_FIELD_SP(X, FROM, TO)               \
       
  2658     GET_FIELD(X, 63 - (TO), 63 - (FROM))
       
  2659 
       
  2660 target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
       
  2661 {
       
  2662     return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
       
  2663         (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
       
  2664         (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
       
  2665         (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
       
  2666         (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
       
  2667         (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
       
  2668         (((pixel_addr >> 55) & 1) << 4) |
       
  2669         (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
       
  2670         GET_FIELD_SP(pixel_addr, 11, 12);
       
  2671 }
       
  2672 
       
  2673 target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
       
  2674 {
       
  2675     uint64_t tmp;
       
  2676 
       
  2677     tmp = addr + offset;
       
  2678     env->gsr &= ~7ULL;
       
  2679     env->gsr |= tmp & 7ULL;
       
  2680     return tmp & ~7ULL;
       
  2681 }
       
  2682 
       
  2683 target_ulong helper_popc(target_ulong val)
       
  2684 {
       
  2685     return ctpop64(val);
       
  2686 }
       
  2687 
       
  2688 static inline uint64_t *get_gregset(uint64_t pstate)
       
  2689 {
       
  2690     switch (pstate) {
       
  2691     default:
       
  2692     case 0:
       
  2693         return env->bgregs;
       
  2694     case PS_AG:
       
  2695         return env->agregs;
       
  2696     case PS_MG:
       
  2697         return env->mgregs;
       
  2698     case PS_IG:
       
  2699         return env->igregs;
       
  2700     }
       
  2701 }
       
  2702 
       
  2703 static inline void change_pstate(uint64_t new_pstate)
       
  2704 {
       
  2705     uint64_t pstate_regs, new_pstate_regs;
       
  2706     uint64_t *src, *dst;
       
  2707 
       
  2708     pstate_regs = env->pstate & 0xc01;
       
  2709     new_pstate_regs = new_pstate & 0xc01;
       
  2710     if (new_pstate_regs != pstate_regs) {
       
  2711         // Switch global register bank
       
  2712         src = get_gregset(new_pstate_regs);
       
  2713         dst = get_gregset(pstate_regs);
       
  2714         memcpy32(dst, env->gregs);
       
  2715         memcpy32(env->gregs, src);
       
  2716     }
       
  2717     env->pstate = new_pstate;
       
  2718 }
       
  2719 
       
  2720 void helper_wrpstate(target_ulong new_state)
       
  2721 {
       
  2722     if (!(env->def->features & CPU_FEATURE_GL))
       
  2723         change_pstate(new_state & 0xf3f);
       
  2724 }
       
  2725 
       
  2726 void helper_done(void)
       
  2727 {
       
  2728     env->pc = env->tsptr->tpc;
       
  2729     env->npc = env->tsptr->tnpc + 4;
       
  2730     PUT_CCR(env, env->tsptr->tstate >> 32);
       
  2731     env->asi = (env->tsptr->tstate >> 24) & 0xff;
       
  2732     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
       
  2733     PUT_CWP64(env, env->tsptr->tstate & 0xff);
       
  2734     env->tl--;
       
  2735     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
       
  2736 }
       
  2737 
       
  2738 void helper_retry(void)
       
  2739 {
       
  2740     env->pc = env->tsptr->tpc;
       
  2741     env->npc = env->tsptr->tnpc;
       
  2742     PUT_CCR(env, env->tsptr->tstate >> 32);
       
  2743     env->asi = (env->tsptr->tstate >> 24) & 0xff;
       
  2744     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
       
  2745     PUT_CWP64(env, env->tsptr->tstate & 0xff);
       
  2746     env->tl--;
       
  2747     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
       
  2748 }
       
  2749 
       
  2750 void helper_set_softint(uint64_t value)
       
  2751 {
       
  2752     env->softint |= (uint32_t)value;
       
  2753 }
       
  2754 
       
  2755 void helper_clear_softint(uint64_t value)
       
  2756 {
       
  2757     env->softint &= (uint32_t)~value;
       
  2758 }
       
  2759 
       
  2760 void helper_write_softint(uint64_t value)
       
  2761 {
       
  2762     env->softint = (uint32_t)value;
       
  2763 }
       
  2764 #endif
       
  2765 
       
  2766 void helper_flush(target_ulong addr)
       
  2767 {
       
  2768     addr &= ~7;
       
  2769     tb_invalidate_page_range(addr, addr + 8);
       
  2770 }
       
  2771 
       
  2772 #ifdef TARGET_SPARC64
       
  2773 #ifdef DEBUG_PCALL
       
  2774 static const char * const excp_names[0x80] = {
       
  2775     [TT_TFAULT] = "Instruction Access Fault",
       
  2776     [TT_TMISS] = "Instruction Access MMU Miss",
       
  2777     [TT_CODE_ACCESS] = "Instruction Access Error",
       
  2778     [TT_ILL_INSN] = "Illegal Instruction",
       
  2779     [TT_PRIV_INSN] = "Privileged Instruction",
       
  2780     [TT_NFPU_INSN] = "FPU Disabled",
       
  2781     [TT_FP_EXCP] = "FPU Exception",
       
  2782     [TT_TOVF] = "Tag Overflow",
       
  2783     [TT_CLRWIN] = "Clean Windows",
       
  2784     [TT_DIV_ZERO] = "Division By Zero",
       
  2785     [TT_DFAULT] = "Data Access Fault",
       
  2786     [TT_DMISS] = "Data Access MMU Miss",
       
  2787     [TT_DATA_ACCESS] = "Data Access Error",
       
  2788     [TT_DPROT] = "Data Protection Error",
       
  2789     [TT_UNALIGNED] = "Unaligned Memory Access",
       
  2790     [TT_PRIV_ACT] = "Privileged Action",
       
  2791     [TT_EXTINT | 0x1] = "External Interrupt 1",
       
  2792     [TT_EXTINT | 0x2] = "External Interrupt 2",
       
  2793     [TT_EXTINT | 0x3] = "External Interrupt 3",
       
  2794     [TT_EXTINT | 0x4] = "External Interrupt 4",
       
  2795     [TT_EXTINT | 0x5] = "External Interrupt 5",
       
  2796     [TT_EXTINT | 0x6] = "External Interrupt 6",
       
  2797     [TT_EXTINT | 0x7] = "External Interrupt 7",
       
  2798     [TT_EXTINT | 0x8] = "External Interrupt 8",
       
  2799     [TT_EXTINT | 0x9] = "External Interrupt 9",
       
  2800     [TT_EXTINT | 0xa] = "External Interrupt 10",
       
  2801     [TT_EXTINT | 0xb] = "External Interrupt 11",
       
  2802     [TT_EXTINT | 0xc] = "External Interrupt 12",
       
  2803     [TT_EXTINT | 0xd] = "External Interrupt 13",
       
  2804     [TT_EXTINT | 0xe] = "External Interrupt 14",
       
  2805     [TT_EXTINT | 0xf] = "External Interrupt 15",
       
  2806 };
       
  2807 #endif
       
  2808 
       
  2809 void do_interrupt(CPUState *env)
       
  2810 {
       
  2811     int intno = env->exception_index;
       
  2812 
       
  2813 #ifdef DEBUG_PCALL
       
  2814     if (loglevel & CPU_LOG_INT) {
       
  2815         static int count;
       
  2816         const char *name;
       
  2817 
       
  2818         if (intno < 0 || intno >= 0x180)
       
  2819             name = "Unknown";
       
  2820         else if (intno >= 0x100)
       
  2821             name = "Trap Instruction";
       
  2822         else if (intno >= 0xc0)
       
  2823             name = "Window Fill";
       
  2824         else if (intno >= 0x80)
       
  2825             name = "Window Spill";
       
  2826         else {
       
  2827             name = excp_names[intno];
       
  2828             if (!name)
       
  2829                 name = "Unknown";
       
  2830         }
       
  2831 
       
  2832         fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
       
  2833                 " SP=%016" PRIx64 "\n",
       
  2834                 count, name, intno,
       
  2835                 env->pc,
       
  2836                 env->npc, env->regwptr[6]);
       
  2837         cpu_dump_state(env, logfile, fprintf, 0);
       
  2838 #if 0
       
  2839         {
       
  2840             int i;
       
  2841             uint8_t *ptr;
       
  2842 
       
  2843             fprintf(logfile, "       code=");
       
  2844             ptr = (uint8_t *)env->pc;
       
  2845             for(i = 0; i < 16; i++) {
       
  2846                 fprintf(logfile, " %02x", ldub(ptr + i));
       
  2847             }
       
  2848             fprintf(logfile, "\n");
       
  2849         }
       
  2850 #endif
       
  2851         count++;
       
  2852     }
       
  2853 #endif
       
  2854 #if !defined(CONFIG_USER_ONLY)
       
  2855     if (env->tl >= env->maxtl) {
       
  2856         cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
       
  2857                   " Error state", env->exception_index, env->tl, env->maxtl);
       
  2858         return;
       
  2859     }
       
  2860 #endif
       
  2861     if (env->tl < env->maxtl - 1) {
       
  2862         env->tl++;
       
  2863     } else {
       
  2864         env->pstate |= PS_RED;
       
  2865         if (env->tl < env->maxtl)
       
  2866             env->tl++;
       
  2867     }
       
  2868     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
       
  2869     env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
       
  2870         ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
       
  2871         GET_CWP64(env);
       
  2872     env->tsptr->tpc = env->pc;
       
  2873     env->tsptr->tnpc = env->npc;
       
  2874     env->tsptr->tt = intno;
       
  2875     if (!(env->def->features & CPU_FEATURE_GL)) {
       
  2876         switch (intno) {
       
  2877         case TT_IVEC:
       
  2878             change_pstate(PS_PEF | PS_PRIV | PS_IG);
       
  2879             break;
       
  2880         case TT_TFAULT:
       
  2881         case TT_TMISS:
       
  2882         case TT_DFAULT:
       
  2883         case TT_DMISS:
       
  2884         case TT_DPROT:
       
  2885             change_pstate(PS_PEF | PS_PRIV | PS_MG);
       
  2886             break;
       
  2887         default:
       
  2888             change_pstate(PS_PEF | PS_PRIV | PS_AG);
       
  2889             break;
       
  2890         }
       
  2891     }
       
  2892     if (intno == TT_CLRWIN)
       
  2893         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
       
  2894     else if ((intno & 0x1c0) == TT_SPILL)
       
  2895         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
       
  2896     else if ((intno & 0x1c0) == TT_FILL)
       
  2897         cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
       
  2898     env->tbr &= ~0x7fffULL;
       
  2899     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
       
  2900     env->pc = env->tbr;
       
  2901     env->npc = env->pc + 4;
       
  2902     env->exception_index = 0;
       
  2903 }
       
  2904 #else
       
  2905 #ifdef DEBUG_PCALL
       
  2906 static const char * const excp_names[0x80] = {
       
  2907     [TT_TFAULT] = "Instruction Access Fault",
       
  2908     [TT_ILL_INSN] = "Illegal Instruction",
       
  2909     [TT_PRIV_INSN] = "Privileged Instruction",
       
  2910     [TT_NFPU_INSN] = "FPU Disabled",
       
  2911     [TT_WIN_OVF] = "Window Overflow",
       
  2912     [TT_WIN_UNF] = "Window Underflow",
       
  2913     [TT_UNALIGNED] = "Unaligned Memory Access",
       
  2914     [TT_FP_EXCP] = "FPU Exception",
       
  2915     [TT_DFAULT] = "Data Access Fault",
       
  2916     [TT_TOVF] = "Tag Overflow",
       
  2917     [TT_EXTINT | 0x1] = "External Interrupt 1",
       
  2918     [TT_EXTINT | 0x2] = "External Interrupt 2",
       
  2919     [TT_EXTINT | 0x3] = "External Interrupt 3",
       
  2920     [TT_EXTINT | 0x4] = "External Interrupt 4",
       
  2921     [TT_EXTINT | 0x5] = "External Interrupt 5",
       
  2922     [TT_EXTINT | 0x6] = "External Interrupt 6",
       
  2923     [TT_EXTINT | 0x7] = "External Interrupt 7",
       
  2924     [TT_EXTINT | 0x8] = "External Interrupt 8",
       
  2925     [TT_EXTINT | 0x9] = "External Interrupt 9",
       
  2926     [TT_EXTINT | 0xa] = "External Interrupt 10",
       
  2927     [TT_EXTINT | 0xb] = "External Interrupt 11",
       
  2928     [TT_EXTINT | 0xc] = "External Interrupt 12",
       
  2929     [TT_EXTINT | 0xd] = "External Interrupt 13",
       
  2930     [TT_EXTINT | 0xe] = "External Interrupt 14",
       
  2931     [TT_EXTINT | 0xf] = "External Interrupt 15",
       
  2932     [TT_TOVF] = "Tag Overflow",
       
  2933     [TT_CODE_ACCESS] = "Instruction Access Error",
       
  2934     [TT_DATA_ACCESS] = "Data Access Error",
       
  2935     [TT_DIV_ZERO] = "Division By Zero",
       
  2936     [TT_NCP_INSN] = "Coprocessor Disabled",
       
  2937 };
       
  2938 #endif
       
  2939 
       
  2940 void do_interrupt(CPUState *env)
       
  2941 {
       
  2942     int cwp, intno = env->exception_index;
       
  2943 
       
  2944 #ifdef DEBUG_PCALL
       
  2945     if (loglevel & CPU_LOG_INT) {
       
  2946         static int count;
       
  2947         const char *name;
       
  2948 
       
  2949         if (intno < 0 || intno >= 0x100)
       
  2950             name = "Unknown";
       
  2951         else if (intno >= 0x80)
       
  2952             name = "Trap Instruction";
       
  2953         else {
       
  2954             name = excp_names[intno];
       
  2955             if (!name)
       
  2956                 name = "Unknown";
       
  2957         }
       
  2958 
       
  2959         fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
       
  2960                 count, name, intno,
       
  2961                 env->pc,
       
  2962                 env->npc, env->regwptr[6]);
       
  2963         cpu_dump_state(env, logfile, fprintf, 0);
       
  2964 #if 0
       
  2965         {
       
  2966             int i;
       
  2967             uint8_t *ptr;
       
  2968 
       
  2969             fprintf(logfile, "       code=");
       
  2970             ptr = (uint8_t *)env->pc;
       
  2971             for(i = 0; i < 16; i++) {
       
  2972                 fprintf(logfile, " %02x", ldub(ptr + i));
       
  2973             }
       
  2974             fprintf(logfile, "\n");
       
  2975         }
       
  2976 #endif
       
  2977         count++;
       
  2978     }
       
  2979 #endif
       
  2980 #if !defined(CONFIG_USER_ONLY)
       
  2981     if (env->psret == 0) {
       
  2982         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
       
  2983                   env->exception_index);
       
  2984         return;
       
  2985     }
       
  2986 #endif
       
  2987     env->psret = 0;
       
  2988     cwp = cpu_cwp_dec(env, env->cwp - 1);
       
  2989     cpu_set_cwp(env, cwp);
       
  2990     env->regwptr[9] = env->pc;
       
  2991     env->regwptr[10] = env->npc;
       
  2992     env->psrps = env->psrs;
       
  2993     env->psrs = 1;
       
  2994     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
       
  2995     env->pc = env->tbr;
       
  2996     env->npc = env->pc + 4;
       
  2997     env->exception_index = 0;
       
  2998 }
       
  2999 #endif
       
  3000 
       
  3001 #if !defined(CONFIG_USER_ONLY)
       
  3002 
       
  3003 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
       
  3004                                 void *retaddr);
       
  3005 
       
  3006 #define MMUSUFFIX _mmu
       
  3007 #define ALIGNED_ONLY
       
  3008 
       
  3009 #define SHIFT 0
       
  3010 #include "softmmu_template.h"
       
  3011 
       
  3012 #define SHIFT 1
       
  3013 #include "softmmu_template.h"
       
  3014 
       
  3015 #define SHIFT 2
       
  3016 #include "softmmu_template.h"
       
  3017 
       
  3018 #define SHIFT 3
       
  3019 #include "softmmu_template.h"
       
  3020 
       
  3021 /* XXX: make it generic ? */
       
  3022 static void cpu_restore_state2(void *retaddr)
       
  3023 {
       
  3024     TranslationBlock *tb;
       
  3025     unsigned long pc;
       
  3026 
       
  3027     if (retaddr) {
       
  3028         /* now we have a real cpu fault */
       
  3029         pc = (unsigned long)retaddr;
       
  3030         tb = tb_find_pc(pc);
       
  3031         if (tb) {
       
  3032             /* the PC is inside the translated code. It means that we have
       
  3033                a virtual CPU fault */
       
  3034             cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
       
  3035         }
       
  3036     }
       
  3037 }
       
  3038 
       
  3039 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
       
  3040                                 void *retaddr)
       
  3041 {
       
  3042 #ifdef DEBUG_UNALIGNED
       
  3043     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
       
  3044            "\n", addr, env->pc);
       
  3045 #endif
       
  3046     cpu_restore_state2(retaddr);
       
  3047     raise_exception(TT_UNALIGNED);
       
  3048 }
       
  3049 
       
  3050 /* try to fill the TLB and return an exception if error. If retaddr is
       
  3051    NULL, it means that the function was called in C code (i.e. not
       
  3052    from generated code or from helper.c) */
       
  3053 /* XXX: fix it to restore all registers */
       
  3054 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
       
  3055 {
       
  3056     int ret;
       
  3057     CPUState *saved_env;
       
  3058 
       
  3059     /* XXX: hack to restore env in all cases, even if not called from
       
  3060        generated code */
       
  3061     saved_env = env;
       
  3062     env = cpu_single_env;
       
  3063 
       
  3064     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
       
  3065     if (ret) {
       
  3066         cpu_restore_state2(retaddr);
       
  3067         cpu_loop_exit();
       
  3068     }
       
  3069     env = saved_env;
       
  3070 }
       
  3071 
       
  3072 #endif
       
  3073 
       
  3074 #ifndef TARGET_SPARC64
       
  3075 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
       
  3076                           int is_asi, int size)
       
  3077 {
       
  3078     CPUState *saved_env;
       
  3079 
       
  3080     /* XXX: hack to restore env in all cases, even if not called from
       
  3081        generated code */
       
  3082     saved_env = env;
       
  3083     env = cpu_single_env;
       
  3084 #ifdef DEBUG_UNASSIGNED
       
  3085     if (is_asi)
       
  3086         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
       
  3087                " asi 0x%02x from " TARGET_FMT_lx "\n",
       
  3088                is_exec ? "exec" : is_write ? "write" : "read", size,
       
  3089                size == 1 ? "" : "s", addr, is_asi, env->pc);
       
  3090     else
       
  3091         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
       
  3092                " from " TARGET_FMT_lx "\n",
       
  3093                is_exec ? "exec" : is_write ? "write" : "read", size,
       
  3094                size == 1 ? "" : "s", addr, env->pc);
       
  3095 #endif
       
  3096     if (env->mmuregs[3]) /* Fault status register */
       
  3097         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
       
  3098     if (is_asi)
       
  3099         env->mmuregs[3] |= 1 << 16;
       
  3100     if (env->psrs)
       
  3101         env->mmuregs[3] |= 1 << 5;
       
  3102     if (is_exec)
       
  3103         env->mmuregs[3] |= 1 << 6;
       
  3104     if (is_write)
       
  3105         env->mmuregs[3] |= 1 << 7;
       
  3106     env->mmuregs[3] |= (5 << 2) | 2;
       
  3107     env->mmuregs[4] = addr; /* Fault address register */
       
  3108     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
       
  3109         if (is_exec)
       
  3110             raise_exception(TT_CODE_ACCESS);
       
  3111         else
       
  3112             raise_exception(TT_DATA_ACCESS);
       
  3113     }
       
  3114     env = saved_env;
       
  3115 }
       
  3116 #else
       
  3117 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
       
  3118                           int is_asi, int size)
       
  3119 {
       
  3120 #ifdef DEBUG_UNASSIGNED
       
  3121     CPUState *saved_env;
       
  3122 
       
  3123     /* XXX: hack to restore env in all cases, even if not called from
       
  3124        generated code */
       
  3125     saved_env = env;
       
  3126     env = cpu_single_env;
       
  3127     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
       
  3128            "\n", addr, env->pc);
       
  3129     env = saved_env;
       
  3130 #endif
       
  3131     if (is_exec)
       
  3132         raise_exception(TT_CODE_ACCESS);
       
  3133     else
       
  3134         raise_exception(TT_DATA_ACCESS);
       
  3135 }
       
  3136 #endif
       
  3137 
       
  3138 #ifdef TARGET_SPARC64
       
  3139 void helper_tick_set_count(void *opaque, uint64_t count)
       
  3140 {
       
  3141 #if !defined(CONFIG_USER_ONLY)
       
  3142     cpu_tick_set_count(opaque, count);
       
  3143 #endif
       
  3144 }
       
  3145 
       
  3146 uint64_t helper_tick_get_count(void *opaque)
       
  3147 {
       
  3148 #if !defined(CONFIG_USER_ONLY)
       
  3149     return cpu_tick_get_count(opaque);
       
  3150 #else
       
  3151     return 0;
       
  3152 #endif
       
  3153 }
       
  3154 
       
  3155 void helper_tick_set_limit(void *opaque, uint64_t limit)
       
  3156 {
       
  3157 #if !defined(CONFIG_USER_ONLY)
       
  3158     cpu_tick_set_limit(opaque, limit);
       
  3159 #endif
       
  3160 }
       
  3161 #endif