translate.c 98.6 KB
Newer Older
1 2 3 4
/*
   SPARC translation

   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
B
bellard 已提交
5
   Copyright (C) 2003-2005 Fabrice Bellard
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
   TODO-list:

B
bellard 已提交
25
   Rest of V9 instructions, VIS instructions
B
bellard 已提交
26
   NPC/PC static optimisations (use JUMP_TB when possible)
27
   Optimize synthetic instructions
B
bellard 已提交
28
   128-bit float
B
bellard 已提交
29
*/
30 31 32 33 34 35 36 37 38 39 40 41 42

#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#include "cpu.h"
#include "exec-all.h"
#include "disas.h"

#define DEBUG_DISAS

B
bellard 已提交
43 44 45 46
#define DYNAMIC_PC  1 /* dynamic pc value */
#define JUMP_PC     2 /* dynamic pc value which takes only two values
                         according to jump_pc[T2] */

47
typedef struct DisasContext {
B
bellard 已提交
48 49 50
    target_ulong pc;	/* current Program Counter: integer or DYNAMIC_PC */
    target_ulong npc;	/* next PC: integer or DYNAMIC_PC or JUMP_PC */
    target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
51
    int is_br;
52
    int mem_idx;
B
bellard 已提交
53
    int fpu_enabled;
54
    struct TranslationBlock *tb;
55 56
} DisasContext;

B
blueswir1 已提交
57 58 59 60 61 62 63
struct sparc_def_t {
    const unsigned char *name;
    target_ulong iu_version;
    uint32_t fpu_version;
    uint32_t mmu_version;
};

64 65 66 67 68 69 70 71 72
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
extern FILE *logfile;
extern int loglevel;

enum {
#define DEF(s,n,copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
73
    NB_OPS
74 75 76 77
};

#include "gen-op.h"

B
bellard 已提交
78
// This function uses non-native bit order
79 80 81
#define GET_FIELD(X, FROM, TO) \
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))

B
bellard 已提交
82 83 84 85 86 87 88 89 90 91
// This function uses the order in the manuals, i.e. bit 0 is 2^0
#define GET_FIELD_SP(X, FROM, TO) \
    GET_FIELD(X, 31 - (TO), 31 - (FROM))

#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), 32 - ((b) - (a) + 1))

#ifdef TARGET_SPARC64
#define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
#else
92
#define DFPREG(r) (r & 0x1e)
B
bellard 已提交
93 94
#endif

B
bellard 已提交
95 96 97 98 99 100
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif

B
bellard 已提交
101 102 103 104 105 106
static int sign_extend(int x, int len)
{
    len = 32 - len;
    return (x << len) >> len;
}

107 108
#define IS_IMM (insn & (1<<13))

109
static void disas_sparc_insn(DisasContext * dc);
110

B
blueswir1 已提交
111
static GenOpFunc * const gen_op_movl_TN_reg[2][32] = {
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    {
     gen_op_movl_g0_T0,
     gen_op_movl_g1_T0,
     gen_op_movl_g2_T0,
     gen_op_movl_g3_T0,
     gen_op_movl_g4_T0,
     gen_op_movl_g5_T0,
     gen_op_movl_g6_T0,
     gen_op_movl_g7_T0,
     gen_op_movl_o0_T0,
     gen_op_movl_o1_T0,
     gen_op_movl_o2_T0,
     gen_op_movl_o3_T0,
     gen_op_movl_o4_T0,
     gen_op_movl_o5_T0,
     gen_op_movl_o6_T0,
     gen_op_movl_o7_T0,
     gen_op_movl_l0_T0,
     gen_op_movl_l1_T0,
     gen_op_movl_l2_T0,
     gen_op_movl_l3_T0,
     gen_op_movl_l4_T0,
     gen_op_movl_l5_T0,
     gen_op_movl_l6_T0,
     gen_op_movl_l7_T0,
     gen_op_movl_i0_T0,
     gen_op_movl_i1_T0,
     gen_op_movl_i2_T0,
     gen_op_movl_i3_T0,
     gen_op_movl_i4_T0,
     gen_op_movl_i5_T0,
     gen_op_movl_i6_T0,
     gen_op_movl_i7_T0,
     },
    {
     gen_op_movl_g0_T1,
     gen_op_movl_g1_T1,
     gen_op_movl_g2_T1,
     gen_op_movl_g3_T1,
     gen_op_movl_g4_T1,
     gen_op_movl_g5_T1,
     gen_op_movl_g6_T1,
     gen_op_movl_g7_T1,
     gen_op_movl_o0_T1,
     gen_op_movl_o1_T1,
     gen_op_movl_o2_T1,
     gen_op_movl_o3_T1,
     gen_op_movl_o4_T1,
     gen_op_movl_o5_T1,
     gen_op_movl_o6_T1,
     gen_op_movl_o7_T1,
     gen_op_movl_l0_T1,
     gen_op_movl_l1_T1,
     gen_op_movl_l2_T1,
     gen_op_movl_l3_T1,
     gen_op_movl_l4_T1,
     gen_op_movl_l5_T1,
     gen_op_movl_l6_T1,
     gen_op_movl_l7_T1,
     gen_op_movl_i0_T1,
     gen_op_movl_i1_T1,
     gen_op_movl_i2_T1,
     gen_op_movl_i3_T1,
     gen_op_movl_i4_T1,
     gen_op_movl_i5_T1,
     gen_op_movl_i6_T1,
     gen_op_movl_i7_T1,
     }
180 181
};

B
blueswir1 已提交
182
static GenOpFunc * const gen_op_movl_reg_TN[3][32] = {
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    {
     gen_op_movl_T0_g0,
     gen_op_movl_T0_g1,
     gen_op_movl_T0_g2,
     gen_op_movl_T0_g3,
     gen_op_movl_T0_g4,
     gen_op_movl_T0_g5,
     gen_op_movl_T0_g6,
     gen_op_movl_T0_g7,
     gen_op_movl_T0_o0,
     gen_op_movl_T0_o1,
     gen_op_movl_T0_o2,
     gen_op_movl_T0_o3,
     gen_op_movl_T0_o4,
     gen_op_movl_T0_o5,
     gen_op_movl_T0_o6,
     gen_op_movl_T0_o7,
     gen_op_movl_T0_l0,
     gen_op_movl_T0_l1,
     gen_op_movl_T0_l2,
     gen_op_movl_T0_l3,
     gen_op_movl_T0_l4,
     gen_op_movl_T0_l5,
     gen_op_movl_T0_l6,
     gen_op_movl_T0_l7,
     gen_op_movl_T0_i0,
     gen_op_movl_T0_i1,
     gen_op_movl_T0_i2,
     gen_op_movl_T0_i3,
     gen_op_movl_T0_i4,
     gen_op_movl_T0_i5,
     gen_op_movl_T0_i6,
     gen_op_movl_T0_i7,
     },
    {
     gen_op_movl_T1_g0,
     gen_op_movl_T1_g1,
     gen_op_movl_T1_g2,
     gen_op_movl_T1_g3,
     gen_op_movl_T1_g4,
     gen_op_movl_T1_g5,
     gen_op_movl_T1_g6,
     gen_op_movl_T1_g7,
     gen_op_movl_T1_o0,
     gen_op_movl_T1_o1,
     gen_op_movl_T1_o2,
     gen_op_movl_T1_o3,
     gen_op_movl_T1_o4,
     gen_op_movl_T1_o5,
     gen_op_movl_T1_o6,
     gen_op_movl_T1_o7,
     gen_op_movl_T1_l0,
     gen_op_movl_T1_l1,
     gen_op_movl_T1_l2,
     gen_op_movl_T1_l3,
     gen_op_movl_T1_l4,
     gen_op_movl_T1_l5,
     gen_op_movl_T1_l6,
     gen_op_movl_T1_l7,
     gen_op_movl_T1_i0,
     gen_op_movl_T1_i1,
     gen_op_movl_T1_i2,
     gen_op_movl_T1_i3,
     gen_op_movl_T1_i4,
     gen_op_movl_T1_i5,
     gen_op_movl_T1_i6,
     gen_op_movl_T1_i7,
     },
    {
     gen_op_movl_T2_g0,
     gen_op_movl_T2_g1,
     gen_op_movl_T2_g2,
     gen_op_movl_T2_g3,
     gen_op_movl_T2_g4,
     gen_op_movl_T2_g5,
     gen_op_movl_T2_g6,
     gen_op_movl_T2_g7,
     gen_op_movl_T2_o0,
     gen_op_movl_T2_o1,
     gen_op_movl_T2_o2,
     gen_op_movl_T2_o3,
     gen_op_movl_T2_o4,
     gen_op_movl_T2_o5,
     gen_op_movl_T2_o6,
     gen_op_movl_T2_o7,
     gen_op_movl_T2_l0,
     gen_op_movl_T2_l1,
     gen_op_movl_T2_l2,
     gen_op_movl_T2_l3,
     gen_op_movl_T2_l4,
     gen_op_movl_T2_l5,
     gen_op_movl_T2_l6,
     gen_op_movl_T2_l7,
     gen_op_movl_T2_i0,
     gen_op_movl_T2_i1,
     gen_op_movl_T2_i2,
     gen_op_movl_T2_i3,
     gen_op_movl_T2_i4,
     gen_op_movl_T2_i5,
     gen_op_movl_T2_i6,
     gen_op_movl_T2_i7,
     }
285 286
};

B
blueswir1 已提交
287
static GenOpFunc1 * const gen_op_movl_TN_im[3] = {
288 289 290
    gen_op_movl_T0_im,
    gen_op_movl_T1_im,
    gen_op_movl_T2_im
291 292
};

B
bellard 已提交
293 294 295 296 297 298 299 300 301
// Sign extending version
static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
    gen_op_movl_T0_sim,
    gen_op_movl_T1_sim,
    gen_op_movl_T2_sim
};

#ifdef TARGET_SPARC64
#define GEN32(func, NAME) \
B
blueswir1 已提交
302
static GenOpFunc * const NAME ## _table [64] = {                              \
B
bellard 已提交
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0,                   \
NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0,                   \
NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0,                   \
NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0,                   \
};                                                                            \
static inline void func(int n)                                                \
{                                                                             \
    NAME ## _table[n]();                                                      \
}
#else
321
#define GEN32(func, NAME) \
B
blueswir1 已提交
322
static GenOpFunc *const NAME ## _table [32] = {                               \
323 324 325 326 327 328 329 330 331 332 333 334 335
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
};                                                                            \
static inline void func(int n)                                                \
{                                                                             \
    NAME ## _table[n]();                                                      \
}
B
bellard 已提交
336
#endif
337 338 339 340 341 342 343 344 345 346 347 348

/* floating point registers moves */
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);

GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);

B
bellard 已提交
349 350 351 352
#ifdef TARGET_SPARC64
// 'a' versions allowed to user depending on asi
#if defined(CONFIG_USER_ONLY)
#define supervisor(dc) 0
B
blueswir1 已提交
353
#define hypervisor(dc) 0
B
bellard 已提交
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
#define gen_op_ldst(name)        gen_op_##name##_raw()
#define OP_LD_TABLE(width)						\
    static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
    {									\
	int asi, offset;						\
									\
	if (IS_IMM) {							\
	    offset = GET_FIELD(insn, 25, 31);				\
	    if (is_ld)							\
		gen_op_ld_asi_reg(offset, size, sign);			\
	    else							\
		gen_op_st_asi_reg(offset, size, sign);			\
	    return;							\
	}								\
	asi = GET_FIELD(insn, 19, 26);					\
	switch (asi) {							\
	case 0x80: /* Primary address space */				\
	    gen_op_##width##_raw();					\
	    break;							\
B
bellard 已提交
373 374 375
	case 0x82: /* Primary address space, non-faulting load */       \
	    gen_op_##width##_raw();					\
	    break;							\
B
bellard 已提交
376 377 378 379 380 381 382 383
	default:							\
            break;							\
	}								\
    }

#else
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
#define OP_LD_TABLE(width)						\
B
blueswir1 已提交
384
    static GenOpFunc * const gen_op_##width[] = {                       \
B
bellard 已提交
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
	&gen_op_##width##_user,						\
	&gen_op_##width##_kernel,					\
    };									\
									\
    static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
    {									\
	int asi, offset;						\
									\
	if (IS_IMM) {							\
	    offset = GET_FIELD(insn, 25, 31);				\
	    if (is_ld)							\
		gen_op_ld_asi_reg(offset, size, sign);			\
	    else							\
		gen_op_st_asi_reg(offset, size, sign);			\
	    return;							\
	}								\
	asi = GET_FIELD(insn, 19, 26);					\
	if (is_ld)							\
	    gen_op_ld_asi(asi, size, sign);				\
	else								\
	    gen_op_st_asi(asi, size, sign);				\
    }

#define supervisor(dc) (dc->mem_idx == 1)
B
blueswir1 已提交
409
#define hypervisor(dc) (dc->mem_idx == 2)
B
bellard 已提交
410 411
#endif
#else
412 413
#if defined(CONFIG_USER_ONLY)
#define gen_op_ldst(name)        gen_op_##name##_raw()
B
bellard 已提交
414
#define OP_LD_TABLE(width)
415 416 417 418
#define supervisor(dc) 0
#else
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
#define OP_LD_TABLE(width)						      \
B
blueswir1 已提交
419
static GenOpFunc * const gen_op_##width[] = {                                 \
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
    &gen_op_##width##_user,                                                   \
    &gen_op_##width##_kernel,                                                 \
};                                                                            \
                                                                              \
static void gen_op_##width##a(int insn, int is_ld, int size, int sign)        \
{                                                                             \
    int asi;                                                                  \
                                                                              \
    asi = GET_FIELD(insn, 19, 26);                                            \
    switch (asi) {                                                            \
	case 10: /* User data access */                                       \
	    gen_op_##width##_user();                                          \
	    break;                                                            \
	case 11: /* Supervisor data access */                                 \
	    gen_op_##width##_kernel();                                        \
	    break;                                                            \
        case 0x20 ... 0x2f: /* MMU passthrough */			      \
	    if (is_ld)                                                        \
		gen_op_ld_asi(asi, size, sign);				      \
	    else                                                              \
		gen_op_st_asi(asi, size, sign);				      \
	    break;                                                            \
	default:                                                              \
	    if (is_ld)                                                        \
		gen_op_ld_asi(asi, size, sign);			              \
	    else                                                              \
		gen_op_st_asi(asi, size, sign);				      \
            break;                                                            \
    }                                                                         \
}

#define supervisor(dc) (dc->mem_idx == 1)
#endif
B
bellard 已提交
453
#endif
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471

OP_LD_TABLE(ld);
OP_LD_TABLE(st);
OP_LD_TABLE(ldub);
OP_LD_TABLE(lduh);
OP_LD_TABLE(ldsb);
OP_LD_TABLE(ldsh);
OP_LD_TABLE(stb);
OP_LD_TABLE(sth);
OP_LD_TABLE(std);
OP_LD_TABLE(ldstub);
OP_LD_TABLE(swap);
OP_LD_TABLE(ldd);
OP_LD_TABLE(stf);
OP_LD_TABLE(stdf);
OP_LD_TABLE(ldf);
OP_LD_TABLE(lddf);

B
bellard 已提交
472 473 474 475 476 477 478 479 480
#ifdef TARGET_SPARC64
OP_LD_TABLE(ldsw);
OP_LD_TABLE(ldx);
OP_LD_TABLE(stx);
OP_LD_TABLE(cas);
OP_LD_TABLE(casx);
#endif

static inline void gen_movl_imm_TN(int reg, uint32_t imm)
481
{
B
bellard 已提交
482
    gen_op_movl_TN_im[reg](imm);
483 484
}

B
bellard 已提交
485
static inline void gen_movl_imm_T1(uint32_t val)
486
{
487
    gen_movl_imm_TN(1, val);
488 489
}

B
bellard 已提交
490
static inline void gen_movl_imm_T0(uint32_t val)
491
{
492
    gen_movl_imm_TN(0, val);
493 494
}

B
bellard 已提交
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
static inline void gen_movl_simm_TN(int reg, int32_t imm)
{
    gen_op_movl_TN_sim[reg](imm);
}

static inline void gen_movl_simm_T1(int32_t val)
{
    gen_movl_simm_TN(1, val);
}

static inline void gen_movl_simm_T0(int32_t val)
{
    gen_movl_simm_TN(0, val);
}

510
static inline void gen_movl_reg_TN(int reg, int t)
511
{
512 513 514 515
    if (reg)
	gen_op_movl_reg_TN[t][reg] ();
    else
	gen_movl_imm_TN(t, 0);
516 517
}

518
static inline void gen_movl_reg_T0(int reg)
519
{
520
    gen_movl_reg_TN(reg, 0);
521 522
}

523
static inline void gen_movl_reg_T1(int reg)
524
{
525
    gen_movl_reg_TN(reg, 1);
526 527
}

528
static inline void gen_movl_reg_T2(int reg)
529
{
530
    gen_movl_reg_TN(reg, 2);
531 532
}

533
static inline void gen_movl_TN_reg(int reg, int t)
534
{
535 536
    if (reg)
	gen_op_movl_TN_reg[t][reg] ();
537 538
}

539
static inline void gen_movl_T0_reg(int reg)
540
{
541
    gen_movl_TN_reg(reg, 0);
542 543
}

544
static inline void gen_movl_T1_reg(int reg)
545
{
546
    gen_movl_TN_reg(reg, 1);
547 548
}

B
bellard 已提交
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
static inline void gen_jmp_im(target_ulong pc)
{
#ifdef TARGET_SPARC64
    if (pc == (uint32_t)pc) {
        gen_op_jmp_im(pc);
    } else {
        gen_op_jmp_im64(pc >> 32, pc);
    }
#else
    gen_op_jmp_im(pc);
#endif
}

static inline void gen_movl_npc_im(target_ulong npc)
{
#ifdef TARGET_SPARC64
    if (npc == (uint32_t)npc) {
        gen_op_movl_npc_im(npc);
    } else {
        gen_op_movq_npc_im64(npc >> 32, npc);
    }
#else
    gen_op_movl_npc_im(npc);
#endif
}

575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
static inline void gen_goto_tb(DisasContext *s, int tb_num, 
                               target_ulong pc, target_ulong npc)
{
    TranslationBlock *tb;

    tb = s->tb;
    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK))  {
        /* jump to same page: we can use a direct jump */
        if (tb_num == 0)
            gen_op_goto_tb0(TBPARAM(tb));
        else
            gen_op_goto_tb1(TBPARAM(tb));
        gen_jmp_im(pc);
        gen_movl_npc_im(npc);
        gen_op_movl_T0_im((long)tb + tb_num);
        gen_op_exit_tb();
    } else {
        /* jump to another page: currently not optimized */
        gen_jmp_im(pc);
        gen_movl_npc_im(npc);
        gen_op_movl_T0_0();
        gen_op_exit_tb();
    }
}

B
bellard 已提交
601 602 603 604 605 606 607 608
static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
{
    int l1;

    l1 = gen_new_label();

    gen_op_jz_T2_label(l1);

609
    gen_goto_tb(dc, 0, pc1, pc1 + 4);
B
bellard 已提交
610 611

    gen_set_label(l1);
612
    gen_goto_tb(dc, 1, pc2, pc2 + 4);
B
bellard 已提交
613 614 615 616 617 618 619 620 621 622
}

static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
{
    int l1;

    l1 = gen_new_label();

    gen_op_jz_T2_label(l1);

623
    gen_goto_tb(dc, 0, pc2, pc1);
B
bellard 已提交
624 625

    gen_set_label(l1);
626
    gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
B
bellard 已提交
627 628 629 630
}

static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
{
631
    gen_goto_tb(dc, 0, pc, npc);
B
bellard 已提交
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
}

static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2)
{
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
    gen_op_jz_T2_label(l1);

    gen_movl_npc_im(npc1);
    gen_op_jmp_label(l2);

    gen_set_label(l1);
    gen_movl_npc_im(npc2);
    gen_set_label(l2);
}

/* call this function before using T2 as it may have been set for a jump */
static inline void flush_T2(DisasContext * dc)
{
    if (dc->npc == JUMP_PC) {
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
        dc->npc = DYNAMIC_PC;
    }
}

B
bellard 已提交
659 660 661
static inline void save_npc(DisasContext * dc)
{
    if (dc->npc == JUMP_PC) {
B
bellard 已提交
662
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
663 664
        dc->npc = DYNAMIC_PC;
    } else if (dc->npc != DYNAMIC_PC) {
B
bellard 已提交
665
        gen_movl_npc_im(dc->npc);
B
bellard 已提交
666 667 668 669 670
    }
}

static inline void save_state(DisasContext * dc)
{
B
bellard 已提交
671
    gen_jmp_im(dc->pc);
B
bellard 已提交
672 673 674
    save_npc(dc);
}

B
bellard 已提交
675 676 677
static inline void gen_mov_pc_npc(DisasContext * dc)
{
    if (dc->npc == JUMP_PC) {
B
bellard 已提交
678
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
679 680 681 682 683 684 685 686 687 688
        gen_op_mov_pc_npc();
        dc->pc = DYNAMIC_PC;
    } else if (dc->npc == DYNAMIC_PC) {
        gen_op_mov_pc_npc();
        dc->pc = DYNAMIC_PC;
    } else {
        dc->pc = dc->npc;
    }
}

B
bellard 已提交
689 690
static GenOpFunc * const gen_cond[2][16] = {
    {
691
	gen_op_eval_bn,
B
bellard 已提交
692 693 694 695 696 697 698
	gen_op_eval_be,
	gen_op_eval_ble,
	gen_op_eval_bl,
	gen_op_eval_bleu,
	gen_op_eval_bcs,
	gen_op_eval_bneg,
	gen_op_eval_bvs,
699
	gen_op_eval_ba,
B
bellard 已提交
700 701 702 703 704 705 706 707 708 709
	gen_op_eval_bne,
	gen_op_eval_bg,
	gen_op_eval_bge,
	gen_op_eval_bgu,
	gen_op_eval_bcc,
	gen_op_eval_bpos,
	gen_op_eval_bvc,
    },
    {
#ifdef TARGET_SPARC64
710
	gen_op_eval_bn,
B
bellard 已提交
711 712 713 714 715 716 717
	gen_op_eval_xbe,
	gen_op_eval_xble,
	gen_op_eval_xbl,
	gen_op_eval_xbleu,
	gen_op_eval_xbcs,
	gen_op_eval_xbneg,
	gen_op_eval_xbvs,
718
	gen_op_eval_ba,
B
bellard 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731
	gen_op_eval_xbne,
	gen_op_eval_xbg,
	gen_op_eval_xbge,
	gen_op_eval_xbgu,
	gen_op_eval_xbcc,
	gen_op_eval_xbpos,
	gen_op_eval_xbvc,
#endif
    },
};

static GenOpFunc * const gen_fcond[4][16] = {
    {
732
	gen_op_eval_bn,
B
bellard 已提交
733 734 735 736 737 738 739
	gen_op_eval_fbne,
	gen_op_eval_fblg,
	gen_op_eval_fbul,
	gen_op_eval_fbl,
	gen_op_eval_fbug,
	gen_op_eval_fbg,
	gen_op_eval_fbu,
740
	gen_op_eval_ba,
B
bellard 已提交
741 742 743 744 745 746 747 748 749 750
	gen_op_eval_fbe,
	gen_op_eval_fbue,
	gen_op_eval_fbge,
	gen_op_eval_fbuge,
	gen_op_eval_fble,
	gen_op_eval_fbule,
	gen_op_eval_fbo,
    },
#ifdef TARGET_SPARC64
    {
751
	gen_op_eval_bn,
B
bellard 已提交
752 753 754 755 756 757 758
	gen_op_eval_fbne_fcc1,
	gen_op_eval_fblg_fcc1,
	gen_op_eval_fbul_fcc1,
	gen_op_eval_fbl_fcc1,
	gen_op_eval_fbug_fcc1,
	gen_op_eval_fbg_fcc1,
	gen_op_eval_fbu_fcc1,
759
	gen_op_eval_ba,
B
bellard 已提交
760 761 762 763 764 765 766 767 768
	gen_op_eval_fbe_fcc1,
	gen_op_eval_fbue_fcc1,
	gen_op_eval_fbge_fcc1,
	gen_op_eval_fbuge_fcc1,
	gen_op_eval_fble_fcc1,
	gen_op_eval_fbule_fcc1,
	gen_op_eval_fbo_fcc1,
    },
    {
769
	gen_op_eval_bn,
B
bellard 已提交
770 771 772 773 774 775 776
	gen_op_eval_fbne_fcc2,
	gen_op_eval_fblg_fcc2,
	gen_op_eval_fbul_fcc2,
	gen_op_eval_fbl_fcc2,
	gen_op_eval_fbug_fcc2,
	gen_op_eval_fbg_fcc2,
	gen_op_eval_fbu_fcc2,
777
	gen_op_eval_ba,
B
bellard 已提交
778 779 780 781 782 783 784 785 786
	gen_op_eval_fbe_fcc2,
	gen_op_eval_fbue_fcc2,
	gen_op_eval_fbge_fcc2,
	gen_op_eval_fbuge_fcc2,
	gen_op_eval_fble_fcc2,
	gen_op_eval_fbule_fcc2,
	gen_op_eval_fbo_fcc2,
    },
    {
787
	gen_op_eval_bn,
B
bellard 已提交
788 789 790 791 792 793 794
	gen_op_eval_fbne_fcc3,
	gen_op_eval_fblg_fcc3,
	gen_op_eval_fbul_fcc3,
	gen_op_eval_fbl_fcc3,
	gen_op_eval_fbug_fcc3,
	gen_op_eval_fbg_fcc3,
	gen_op_eval_fbu_fcc3,
795
	gen_op_eval_ba,
B
bellard 已提交
796 797 798 799 800 801 802 803 804 805 806 807
	gen_op_eval_fbe_fcc3,
	gen_op_eval_fbue_fcc3,
	gen_op_eval_fbge_fcc3,
	gen_op_eval_fbuge_fcc3,
	gen_op_eval_fble_fcc3,
	gen_op_eval_fbule_fcc3,
	gen_op_eval_fbo_fcc3,
    },
#else
    {}, {}, {},
#endif
};
808

B
bellard 已提交
809 810
#ifdef TARGET_SPARC64
static void gen_cond_reg(int cond)
811 812 813
{
	switch (cond) {
	case 0x1:
B
bellard 已提交
814
	    gen_op_eval_brz();
815 816
	    break;
	case 0x2:
B
bellard 已提交
817
	    gen_op_eval_brlez();
818 819
	    break;
	case 0x3:
B
bellard 已提交
820
	    gen_op_eval_brlz();
821 822
	    break;
	case 0x5:
B
bellard 已提交
823
	    gen_op_eval_brnz();
824 825
	    break;
	case 0x6:
B
bellard 已提交
826
	    gen_op_eval_brgz();
827 828
	    break;
        default:
B
bellard 已提交
829 830
	case 0x7:
	    gen_op_eval_brgez();
831 832 833
	    break;
	}
}
B
bellard 已提交
834
#endif
835

B
bellard 已提交
836
/* XXX: potentially incorrect if dynamic npc */
B
bellard 已提交
837
static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
838
{
839
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
840
    target_ulong target = dc->pc + offset;
B
bellard 已提交
841
	
842 843 844
    if (cond == 0x0) {
	/* unconditional not taken */
	if (a) {
B
bellard 已提交
845
	    dc->pc = dc->npc + 4; 
846 847 848 849 850 851 852 853
	    dc->npc = dc->pc + 4;
	} else {
	    dc->pc = dc->npc;
	    dc->npc = dc->pc + 4;
	}
    } else if (cond == 0x8) {
	/* unconditional taken */
	if (a) {
B
bellard 已提交
854
	    dc->pc = target;
855 856 857
	    dc->npc = dc->pc + 4;
	} else {
	    dc->pc = dc->npc;
B
bellard 已提交
858
	    dc->npc = target;
859 860
	}
    } else {
B
bellard 已提交
861
        flush_T2(dc);
B
bellard 已提交
862
        gen_cond[cc][cond]();
863
	if (a) {
B
bellard 已提交
864
	    gen_branch_a(dc, (long)dc->tb, target, dc->npc);
865 866 867
            dc->is_br = 1;
	} else {
            dc->pc = dc->npc;
B
bellard 已提交
868 869 870
            dc->jump_pc[0] = target;
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
871 872
	}
    }
873 874
}

B
bellard 已提交
875
/* XXX: potentially incorrect if dynamic npc */
B
bellard 已提交
876
static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
877 878
{
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
879 880
    target_ulong target = dc->pc + offset;

881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
    if (cond == 0x0) {
	/* unconditional not taken */
	if (a) {
	    dc->pc = dc->npc + 4;
	    dc->npc = dc->pc + 4;
	} else {
	    dc->pc = dc->npc;
	    dc->npc = dc->pc + 4;
	}
    } else if (cond == 0x8) {
	/* unconditional taken */
	if (a) {
	    dc->pc = target;
	    dc->npc = dc->pc + 4;
	} else {
	    dc->pc = dc->npc;
	    dc->npc = target;
	}
    } else {
        flush_T2(dc);
B
bellard 已提交
901
        gen_fcond[cc][cond]();
902
	if (a) {
B
bellard 已提交
903
	    gen_branch_a(dc, (long)dc->tb, target, dc->npc);
904 905 906 907 908 909 910 911 912 913
            dc->is_br = 1;
	} else {
            dc->pc = dc->npc;
            dc->jump_pc[0] = target;
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
	}
    }
}

B
bellard 已提交
914 915 916
#ifdef TARGET_SPARC64
/* XXX: potentially incorrect if dynamic npc */
static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
917
{
B
bellard 已提交
918 919 920 921 922 923
    unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
    target_ulong target = dc->pc + offset;

    flush_T2(dc);
    gen_cond_reg(cond);
    if (a) {
B
bellard 已提交
924
	gen_branch_a(dc, (long)dc->tb, target, dc->npc);
B
bellard 已提交
925 926 927 928 929 930 931
	dc->is_br = 1;
    } else {
	dc->pc = dc->npc;
	dc->jump_pc[0] = target;
	dc->jump_pc[1] = dc->npc + 4;
	dc->npc = JUMP_PC;
    }
932 933
}

B
bellard 已提交
934 935 936 937 938 939 940 941 942 943 944 945 946
static GenOpFunc * const gen_fcmps[4] = {
    gen_op_fcmps,
    gen_op_fcmps_fcc1,
    gen_op_fcmps_fcc2,
    gen_op_fcmps_fcc3,
};

static GenOpFunc * const gen_fcmpd[4] = {
    gen_op_fcmpd,
    gen_op_fcmpd_fcc1,
    gen_op_fcmpd_fcc2,
    gen_op_fcmpd_fcc3,
};
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961

static GenOpFunc * const gen_fcmpes[4] = {
    gen_op_fcmpes,
    gen_op_fcmpes_fcc1,
    gen_op_fcmpes_fcc2,
    gen_op_fcmpes_fcc3,
};

static GenOpFunc * const gen_fcmped[4] = {
    gen_op_fcmped,
    gen_op_fcmped_fcc1,
    gen_op_fcmped_fcc2,
    gen_op_fcmped_fcc3,
};

B
bellard 已提交
962 963
#endif

B
bellard 已提交
964 965 966 967 968 969 970 971 972 973 974 975 976
static int gen_trap_ifnofpu(DisasContext * dc)
{
#if !defined(CONFIG_USER_ONLY)
    if (!dc->fpu_enabled) {
        save_state(dc);
        gen_op_exception(TT_NFPU_INSN);
        dc->is_br = 1;
        return 1;
    }
#endif
    return 0;
}

B
bellard 已提交
977
/* before an instruction, dc->pc must be static */
978 979 980
static void disas_sparc_insn(DisasContext * dc)
{
    unsigned int insn, opc, rs1, rs2, rd;
981

B
bellard 已提交
982
    insn = ldl_code(dc->pc);
983
    opc = GET_FIELD(insn, 0, 1);
984

985 986 987 988 989
    rd = GET_FIELD(insn, 2, 6);
    switch (opc) {
    case 0:			/* branches/sethi */
	{
	    unsigned int xop = GET_FIELD(insn, 7, 9);
990
	    int32_t target;
991
	    switch (xop) {
B
bellard 已提交
992
#ifdef TARGET_SPARC64
993
	    case 0x1:		/* V9 BPcc */
B
bellard 已提交
994 995 996 997 998
		{
		    int cc;

		    target = GET_FIELD_SP(insn, 0, 18);
		    target = sign_extend(target, 18);
B
bellard 已提交
999
		    target <<= 2;
B
bellard 已提交
1000 1001 1002 1003 1004 1005 1006 1007 1008
		    cc = GET_FIELD_SP(insn, 20, 21);
		    if (cc == 0)
			do_branch(dc, target, insn, 0);
		    else if (cc == 2)
			do_branch(dc, target, insn, 1);
		    else
			goto illegal_insn;
		    goto jmp_insn;
		}
1009
	    case 0x3:		/* V9 BPr */
B
bellard 已提交
1010 1011
		{
		    target = GET_FIELD_SP(insn, 0, 13) | 
1012
                        (GET_FIELD_SP(insn, 20, 21) << 14);
B
bellard 已提交
1013
		    target = sign_extend(target, 16);
B
bellard 已提交
1014
		    target <<= 2;
B
bellard 已提交
1015
		    rs1 = GET_FIELD(insn, 13, 17);
B
bellard 已提交
1016
		    gen_movl_reg_T0(rs1);
B
bellard 已提交
1017 1018 1019
		    do_branch_reg(dc, target, insn);
		    goto jmp_insn;
		}
1020
	    case 0x5:		/* V9 FBPcc */
B
bellard 已提交
1021 1022
		{
		    int cc = GET_FIELD_SP(insn, 20, 21);
B
bellard 已提交
1023 1024
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
B
bellard 已提交
1025 1026
		    target = GET_FIELD_SP(insn, 0, 18);
		    target = sign_extend(target, 19);
B
bellard 已提交
1027
		    target <<= 2;
B
bellard 已提交
1028 1029 1030
		    do_fbranch(dc, target, insn, cc);
		    goto jmp_insn;
		}
1031 1032 1033 1034 1035
#else
	    case 0x7:		/* CBN+x */
		{
		    goto ncp_insn;
		}
B
bellard 已提交
1036
#endif
1037
	    case 0x2:		/* BN+x */
1038
		{
B
bellard 已提交
1039
		    target = GET_FIELD(insn, 10, 31);
1040
		    target = sign_extend(target, 22);
B
bellard 已提交
1041
		    target <<= 2;
B
bellard 已提交
1042
		    do_branch(dc, target, insn, 0);
1043
		    goto jmp_insn;
1044
		}
1045 1046
	    case 0x6:		/* FBN+x */
		{
B
bellard 已提交
1047 1048
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
B
bellard 已提交
1049
		    target = GET_FIELD(insn, 10, 31);
1050
		    target = sign_extend(target, 22);
B
bellard 已提交
1051
		    target <<= 2;
B
bellard 已提交
1052
		    do_fbranch(dc, target, insn, 0);
1053 1054
		    goto jmp_insn;
		}
1055
	    case 0x4:		/* SETHI */
B
bellard 已提交
1056 1057 1058 1059
#define OPTIM
#if defined(OPTIM)
		if (rd) { // nop
#endif
B
bellard 已提交
1060 1061
		    uint32_t value = GET_FIELD(insn, 10, 31);
		    gen_movl_imm_T0(value << 10);
B
bellard 已提交
1062 1063 1064 1065
		    gen_movl_T0_reg(rd);
#if defined(OPTIM)
		}
#endif
1066
		break;
B
bellard 已提交
1067 1068 1069
	    case 0x0:		/* UNIMPL */
	    default:
                goto illegal_insn;
1070 1071 1072
	    }
	    break;
	}
1073
	break;
1074 1075
    case 1:
	/*CALL*/ {
1076
	    target_long target = GET_FIELDs(insn, 2, 31) << 2;
1077

B
bellard 已提交
1078 1079 1080 1081 1082 1083 1084
#ifdef TARGET_SPARC64
	    if (dc->pc == (uint32_t)dc->pc) {
		gen_op_movl_T0_im(dc->pc);
	    } else {
		gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
	    }
#else
1085
	    gen_op_movl_T0_im(dc->pc);
B
bellard 已提交
1086
#endif
1087
	    gen_movl_T0_reg(15);
1088
	    target += dc->pc;
B
bellard 已提交
1089
            gen_mov_pc_npc(dc);
B
bellard 已提交
1090
	    dc->npc = target;
1091 1092 1093 1094 1095 1096 1097
	}
	goto jmp_insn;
    case 2:			/* FPU & Logical Operations */
	{
	    unsigned int xop = GET_FIELD(insn, 7, 12);
	    if (xop == 0x3a) {	/* generate trap */
                int cond;
B
bellard 已提交
1098

1099 1100 1101
                rs1 = GET_FIELD(insn, 13, 17);
                gen_movl_reg_T0(rs1);
		if (IS_IMM) {
1102
		    rs2 = GET_FIELD(insn, 25, 31);
B
bellard 已提交
1103
#if defined(OPTIM)
1104
		    if (rs2 != 0) {
B
bellard 已提交
1105
#endif
B
bellard 已提交
1106
			gen_movl_simm_T1(rs2);
B
bellard 已提交
1107 1108
			gen_op_add_T1_T0();
#if defined(OPTIM)
1109
		    }
B
bellard 已提交
1110
#endif
1111 1112
                } else {
                    rs2 = GET_FIELD(insn, 27, 31);
B
bellard 已提交
1113 1114 1115 1116 1117 1118 1119 1120
#if defined(OPTIM)
		    if (rs2 != 0) {
#endif
			gen_movl_reg_T1(rs2);
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
#endif
1121 1122 1123
                }
                cond = GET_FIELD(insn, 3, 6);
                if (cond == 0x8) {
B
bellard 已提交
1124
                    save_state(dc);
1125
                    gen_op_trap_T0();
1126
                } else if (cond != 0) {
B
bellard 已提交
1127 1128 1129
#ifdef TARGET_SPARC64
		    /* V9 icc/xcc */
		    int cc = GET_FIELD_SP(insn, 11, 12);
B
bellard 已提交
1130 1131
		    flush_T2(dc);
                    save_state(dc);
B
bellard 已提交
1132 1133 1134 1135 1136 1137 1138
		    if (cc == 0)
			gen_cond[0][cond]();
		    else if (cc == 2)
			gen_cond[1][cond]();
		    else
			goto illegal_insn;
#else
B
bellard 已提交
1139 1140
		    flush_T2(dc);
                    save_state(dc);
B
bellard 已提交
1141 1142
		    gen_cond[0][cond]();
#endif
1143 1144
                    gen_op_trapcc_T0();
                }
B
bellard 已提交
1145 1146 1147 1148 1149
                gen_op_next_insn();
                gen_op_movl_T0_0();
                gen_op_exit_tb();
                dc->is_br = 1;
                goto jmp_insn;
1150 1151 1152 1153
            } else if (xop == 0x28) {
                rs1 = GET_FIELD(insn, 13, 17);
                switch(rs1) {
                case 0: /* rdy */
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
#ifndef TARGET_SPARC64
                case 0x01 ... 0x0e: /* undefined in the SPARCv8
                                       manual, rdy on the microSPARC
                                       II */
                case 0x0f:          /* stbar in the SPARCv8 manual,
                                       rdy on the microSPARC II */
                case 0x10 ... 0x1f: /* implementation-dependent in the
                                       SPARCv8 manual, rdy on the
                                       microSPARC II */
#endif
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
1165 1166
                    gen_movl_T0_reg(rd);
                    break;
B
bellard 已提交
1167
#ifdef TARGET_SPARC64
1168
		case 0x2: /* V9 rdccr */
B
bellard 已提交
1169 1170 1171
                    gen_op_rdccr();
                    gen_movl_T0_reg(rd);
                    break;
1172
		case 0x3: /* V9 rdasi */
B
bellard 已提交
1173 1174 1175
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
                    gen_movl_T0_reg(rd);
                    break;
1176
		case 0x4: /* V9 rdtick */
B
bellard 已提交
1177 1178 1179
                    gen_op_rdtick();
                    gen_movl_T0_reg(rd);
                    break;
1180
		case 0x5: /* V9 rdpc */
P
pbrook 已提交
1181 1182 1183 1184 1185
		    if (dc->pc == (uint32_t)dc->pc) {
			gen_op_movl_T0_im(dc->pc);
		    } else {
			gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
		    }
B
bellard 已提交
1186 1187
		    gen_movl_T0_reg(rd);
		    break;
1188
		case 0x6: /* V9 rdfprs */
B
bellard 已提交
1189 1190 1191
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
                    gen_movl_T0_reg(rd);
                    break;
1192 1193
                case 0xf: /* V9 membar */
                    break; /* no effect */
B
bellard 已提交
1194 1195 1196 1197 1198 1199
		case 0x13: /* Graphics Status */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
                    gen_movl_T0_reg(rd);
                    break;
B
bellard 已提交
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
		case 0x17: /* Tick compare */
		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
                    gen_movl_T0_reg(rd);
                    break;
		case 0x18: /* System tick */
                    gen_op_rdtick(); // XXX
                    gen_movl_T0_reg(rd);
                    break;
		case 0x19: /* System tick compare */
		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
                    gen_movl_T0_reg(rd);
                    break;
		case 0x10: /* Performance Control */
		case 0x11: /* Performance Instrumentation Counter */
		case 0x12: /* Dispatch Control */
		case 0x14: /* Softint set, WO */
		case 0x15: /* Softint clear, WO */
		case 0x16: /* Softint write */
B
bellard 已提交
1218 1219
#endif
                default:
1220 1221
                    goto illegal_insn;
                }
1222
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
1223
            } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
B
bellard 已提交
1224
#ifndef TARGET_SPARC64
1225 1226 1227
		if (!supervisor(dc))
		    goto priv_insn;
                gen_op_rdpsr();
B
blueswir1 已提交
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
#else
                if (!hypervisor(dc))
                    goto priv_insn;
                rs1 = GET_FIELD(insn, 13, 17);
                switch (rs1) {
                case 0: // hpstate
                    // gen_op_rdhpstate();
                    break;
                case 1: // htstate
                    // gen_op_rdhtstate();
                    break;
                case 3: // hintp
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, hintp));
                    break;
                case 5: // htba
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, htba));
                    break;
                case 6: // hver
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, hver));
                    break;
                case 31: // hstick_cmpr
                    gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
                    break;
                default:
                    goto illegal_insn;
                }
#endif
1255 1256
                gen_movl_T0_reg(rd);
                break;
B
bellard 已提交
1257
            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1258 1259
		if (!supervisor(dc))
		    goto priv_insn;
B
bellard 已提交
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
#ifdef TARGET_SPARC64
                rs1 = GET_FIELD(insn, 13, 17);
		switch (rs1) {
		case 0: // tpc
		    gen_op_rdtpc();
		    break;
		case 1: // tnpc
		    gen_op_rdtnpc();
		    break;
		case 2: // tstate
		    gen_op_rdtstate();
		    break;
		case 3: // tt
		    gen_op_rdtt();
		    break;
		case 4: // tick
		    gen_op_rdtick();
		    break;
		case 5: // tba
		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
		    break;
		case 6: // pstate
		    gen_op_rdpstate();
		    break;
		case 7: // tl
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
		    break;
		case 8: // pil
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
		    break;
		case 9: // cwp
		    gen_op_rdcwp();
		    break;
		case 10: // cansave
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
		    break;
		case 11: // canrestore
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
		    break;
		case 12: // cleanwin
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
		    break;
		case 13: // otherwin
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
		    break;
		case 14: // wstate
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
		    break;
B
blueswir1 已提交
1308 1309 1310 1311 1312 1313 1314 1315
                case 16: // UA2005 gl
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, gl));
                    break;
                case 26: // UA2005 strand status
                    if (!hypervisor(dc))
                        goto priv_insn;
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, ssr));
                    break;
B
bellard 已提交
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
		case 31: // ver
		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
		    break;
		case 15: // fq
		default:
		    goto illegal_insn;
		}
#else
		gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
#endif
1326 1327
                gen_movl_T0_reg(rd);
                break;
B
bellard 已提交
1328 1329 1330 1331
            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
		gen_op_flushw();
#else
1332 1333
		if (!supervisor(dc))
		    goto priv_insn;
B
bellard 已提交
1334
		gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1335
                gen_movl_T0_reg(rd);
B
bellard 已提交
1336
#endif
1337 1338
                break;
#endif
B
bellard 已提交
1339
	    } else if (xop == 0x34) {	/* FPU Operations */
B
bellard 已提交
1340 1341
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
1342
		gen_op_clear_ieee_excp_and_FTT();
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
                rs1 = GET_FIELD(insn, 13, 17);
	        rs2 = GET_FIELD(insn, 27, 31);
	        xop = GET_FIELD(insn, 18, 26);
		switch (xop) {
		    case 0x1: /* fmovs */
                	gen_op_load_fpr_FT0(rs2);
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x5: /* fnegs */
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fnegs();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x9: /* fabss */
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fabss();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x29: /* fsqrts */
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fsqrts();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x2a: /* fsqrtd */
B
bellard 已提交
1367
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1368
			gen_op_fsqrtd();
B
bellard 已提交
1369
			gen_op_store_DT0_fpr(DFPREG(rd));
1370
			break;
B
bellard 已提交
1371 1372
		    case 0x2b: /* fsqrtq */
		        goto nfpu_insn;
1373 1374 1375 1376 1377 1378 1379
		    case 0x41:
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fadds();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x42:
B
bellard 已提交
1380 1381
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1382
			gen_op_faddd();
B
bellard 已提交
1383
			gen_op_store_DT0_fpr(DFPREG(rd));
1384
			break;
B
bellard 已提交
1385 1386
		    case 0x43: /* faddq */
		        goto nfpu_insn;
1387 1388 1389 1390 1391 1392 1393
		    case 0x45:
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fsubs();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x46:
B
bellard 已提交
1394 1395
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1396
			gen_op_fsubd();
B
bellard 已提交
1397
			gen_op_store_DT0_fpr(DFPREG(rd));
1398
			break;
B
bellard 已提交
1399 1400
		    case 0x47: /* fsubq */
		        goto nfpu_insn;
1401 1402 1403 1404 1405 1406 1407
		    case 0x49:
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fmuls();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x4a:
B
bellard 已提交
1408 1409
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1410 1411 1412
			gen_op_fmuld();
			gen_op_store_DT0_fpr(rd);
			break;
B
bellard 已提交
1413 1414
		    case 0x4b: /* fmulq */
		        goto nfpu_insn;
1415 1416 1417 1418 1419 1420 1421
		    case 0x4d:
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fdivs();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x4e:
B
bellard 已提交
1422 1423
                	gen_op_load_fpr_DT0(DFPREG(rs1));
			gen_op_load_fpr_DT1(DFPREG(rs2));
1424
			gen_op_fdivd();
B
bellard 已提交
1425
			gen_op_store_DT0_fpr(DFPREG(rd));
1426
			break;
B
bellard 已提交
1427 1428
		    case 0x4f: /* fdivq */
		        goto nfpu_insn;
1429 1430 1431 1432
		    case 0x69:
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fsmuld();
B
bellard 已提交
1433
			gen_op_store_DT0_fpr(DFPREG(rd));
1434
			break;
B
bellard 已提交
1435 1436
		    case 0x6e: /* fdmulq */
		        goto nfpu_insn;
1437 1438 1439 1440 1441 1442
		    case 0xc4:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fitos();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0xc6:
B
bellard 已提交
1443
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1444 1445 1446
			gen_op_fdtos();
			gen_op_store_FT0_fpr(rd);
			break;
B
bellard 已提交
1447 1448
		    case 0xc7: /* fqtos */
		        goto nfpu_insn;
1449 1450 1451
		    case 0xc8:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fitod();
B
bellard 已提交
1452
			gen_op_store_DT0_fpr(DFPREG(rd));
1453 1454 1455 1456
			break;
		    case 0xc9:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fstod();
B
bellard 已提交
1457
			gen_op_store_DT0_fpr(DFPREG(rd));
1458
			break;
B
bellard 已提交
1459 1460 1461 1462 1463 1464 1465 1466
		    case 0xcb: /* fqtod */
		        goto nfpu_insn;
		    case 0xcc: /* fitoq */
		        goto nfpu_insn;
		    case 0xcd: /* fstoq */
		        goto nfpu_insn;
		    case 0xce: /* fdtoq */
		        goto nfpu_insn;
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
		    case 0xd1:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fstoi();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0xd2:
                	gen_op_load_fpr_DT1(rs2);
			gen_op_fdtoi();
			gen_op_store_FT0_fpr(rd);
			break;
B
bellard 已提交
1477 1478
		    case 0xd3: /* fqtoi */
		        goto nfpu_insn;
B
bellard 已提交
1479
#ifdef TARGET_SPARC64
1480
		    case 0x2: /* V9 fmovd */
B
bellard 已提交
1481 1482 1483
                	gen_op_load_fpr_DT0(DFPREG(rs2));
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1484
		    case 0x6: /* V9 fnegd */
B
bellard 已提交
1485 1486 1487 1488
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fnegd();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1489
		    case 0xa: /* V9 fabsd */
B
bellard 已提交
1490 1491 1492 1493
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fabsd();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1494
		    case 0x81: /* V9 fstox */
B
bellard 已提交
1495 1496 1497 1498
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fstox();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1499
		    case 0x82: /* V9 fdtox */
B
bellard 已提交
1500 1501 1502 1503
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fdtox();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1504
		    case 0x84: /* V9 fxtos */
B
bellard 已提交
1505 1506 1507 1508
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fxtos();
			gen_op_store_FT0_fpr(rd);
			break;
1509
		    case 0x88: /* V9 fxtod */
B
bellard 已提交
1510 1511 1512 1513
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fxtod();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1514 1515 1516 1517 1518
		    case 0x3: /* V9 fmovq */
		    case 0x7: /* V9 fnegq */
		    case 0xb: /* V9 fabsq */
		    case 0x83: /* V9 fqtox */
		    case 0x8c: /* V9 fxtoq */
B
bellard 已提交
1519 1520 1521
		        goto nfpu_insn;
#endif
		    default:
1522 1523
                	goto illegal_insn;
		}
B
bellard 已提交
1524
	    } else if (xop == 0x35) {	/* FPU Operations */
B
bellard 已提交
1525 1526 1527
#ifdef TARGET_SPARC64
		int cond;
#endif
B
bellard 已提交
1528 1529
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
1530
		gen_op_clear_ieee_excp_and_FTT();
1531
                rs1 = GET_FIELD(insn, 13, 17);
B
bellard 已提交
1532 1533
	        rs2 = GET_FIELD(insn, 27, 31);
	        xop = GET_FIELD(insn, 18, 26);
B
bellard 已提交
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
#ifdef TARGET_SPARC64
		if ((xop & 0x11f) == 0x005) { // V9 fmovsr
		    cond = GET_FIELD_SP(insn, 14, 17);
		    gen_op_load_fpr_FT0(rd);
		    gen_op_load_fpr_FT1(rs2);
		    rs1 = GET_FIELD(insn, 13, 17);
		    gen_movl_reg_T0(rs1);
		    flush_T2(dc);
		    gen_cond_reg(cond);
		    gen_op_fmovs_cc();
		    gen_op_store_FT0_fpr(rd);
		    break;
		} else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
		    cond = GET_FIELD_SP(insn, 14, 17);
		    gen_op_load_fpr_DT0(rd);
		    gen_op_load_fpr_DT1(rs2);
		    flush_T2(dc);
		    rs1 = GET_FIELD(insn, 13, 17);
		    gen_movl_reg_T0(rs1);
		    gen_cond_reg(cond);
		    gen_op_fmovs_cc();
		    gen_op_store_DT0_fpr(rd);
		    break;
		} else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
		    goto nfpu_insn;
		}
#endif
B
bellard 已提交
1561
		switch (xop) {
B
bellard 已提交
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684
#ifdef TARGET_SPARC64
		    case 0x001: /* V9 fmovscc %fcc0 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_FT0(rd);
                	gen_op_load_fpr_FT1(rs2);
			flush_T2(dc);
			gen_fcond[0][cond]();
			gen_op_fmovs_cc();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x002: /* V9 fmovdcc %fcc0 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_DT0(rd);
                	gen_op_load_fpr_DT1(rs2);
			flush_T2(dc);
			gen_fcond[0][cond]();
			gen_op_fmovd_cc();
			gen_op_store_DT0_fpr(rd);
			break;
		    case 0x003: /* V9 fmovqcc %fcc0 */
		        goto nfpu_insn;
		    case 0x041: /* V9 fmovscc %fcc1 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_FT0(rd);
                	gen_op_load_fpr_FT1(rs2);
			flush_T2(dc);
			gen_fcond[1][cond]();
			gen_op_fmovs_cc();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x042: /* V9 fmovdcc %fcc1 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_DT0(rd);
                	gen_op_load_fpr_DT1(rs2);
			flush_T2(dc);
			gen_fcond[1][cond]();
			gen_op_fmovd_cc();
			gen_op_store_DT0_fpr(rd);
			break;
		    case 0x043: /* V9 fmovqcc %fcc1 */
		        goto nfpu_insn;
		    case 0x081: /* V9 fmovscc %fcc2 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_FT0(rd);
                	gen_op_load_fpr_FT1(rs2);
			flush_T2(dc);
			gen_fcond[2][cond]();
			gen_op_fmovs_cc();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x082: /* V9 fmovdcc %fcc2 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_DT0(rd);
                	gen_op_load_fpr_DT1(rs2);
			flush_T2(dc);
			gen_fcond[2][cond]();
			gen_op_fmovd_cc();
			gen_op_store_DT0_fpr(rd);
			break;
		    case 0x083: /* V9 fmovqcc %fcc2 */
		        goto nfpu_insn;
		    case 0x0c1: /* V9 fmovscc %fcc3 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_FT0(rd);
                	gen_op_load_fpr_FT1(rs2);
			flush_T2(dc);
			gen_fcond[3][cond]();
			gen_op_fmovs_cc();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x0c2: /* V9 fmovdcc %fcc3 */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_DT0(rd);
                	gen_op_load_fpr_DT1(rs2);
			flush_T2(dc);
			gen_fcond[3][cond]();
			gen_op_fmovd_cc();
			gen_op_store_DT0_fpr(rd);
			break;
		    case 0x0c3: /* V9 fmovqcc %fcc3 */
		        goto nfpu_insn;
		    case 0x101: /* V9 fmovscc %icc */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_FT0(rd);
                	gen_op_load_fpr_FT1(rs2);
			flush_T2(dc);
			gen_cond[0][cond]();
			gen_op_fmovs_cc();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x102: /* V9 fmovdcc %icc */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_DT0(rd);
                	gen_op_load_fpr_DT1(rs2);
			flush_T2(dc);
			gen_cond[0][cond]();
			gen_op_fmovd_cc();
			gen_op_store_DT0_fpr(rd);
			break;
		    case 0x103: /* V9 fmovqcc %icc */
		        goto nfpu_insn;
		    case 0x181: /* V9 fmovscc %xcc */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_FT0(rd);
                	gen_op_load_fpr_FT1(rs2);
			flush_T2(dc);
			gen_cond[1][cond]();
			gen_op_fmovs_cc();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0x182: /* V9 fmovdcc %xcc */
			cond = GET_FIELD_SP(insn, 14, 17);
                	gen_op_load_fpr_DT0(rd);
                	gen_op_load_fpr_DT1(rs2);
			flush_T2(dc);
			gen_cond[1][cond]();
			gen_op_fmovd_cc();
			gen_op_store_DT0_fpr(rd);
			break;
		    case 0x183: /* V9 fmovqcc %xcc */
		        goto nfpu_insn;
#endif
		    case 0x51: /* V9 %fcc */
B
bellard 已提交
1685 1686
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
B
bellard 已提交
1687 1688 1689
#ifdef TARGET_SPARC64
			gen_fcmps[rd & 3]();
#else
B
bellard 已提交
1690
			gen_op_fcmps();
B
bellard 已提交
1691
#endif
B
bellard 已提交
1692
			break;
B
bellard 已提交
1693 1694 1695 1696 1697 1698
		    case 0x52: /* V9 %fcc */
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
#ifdef TARGET_SPARC64
			gen_fcmpd[rd & 3]();
#else
B
bellard 已提交
1699
			gen_op_fcmpd();
B
bellard 已提交
1700
#endif
B
bellard 已提交
1701 1702 1703
			break;
		    case 0x53: /* fcmpq */
		        goto nfpu_insn;
B
bellard 已提交
1704
		    case 0x55: /* fcmpes, V9 %fcc */
B
bellard 已提交
1705 1706
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
B
bellard 已提交
1707
#ifdef TARGET_SPARC64
1708
			gen_fcmpes[rd & 3]();
B
bellard 已提交
1709
#else
1710
			gen_op_fcmpes();
B
bellard 已提交
1711
#endif
B
bellard 已提交
1712
			break;
B
bellard 已提交
1713 1714 1715 1716
		    case 0x56: /* fcmped, V9 %fcc */
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
#ifdef TARGET_SPARC64
1717
			gen_fcmped[rd & 3]();
B
bellard 已提交
1718
#else
1719
			gen_op_fcmped();
B
bellard 已提交
1720
#endif
B
bellard 已提交
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
			break;
		    case 0x57: /* fcmpeq */
		        goto nfpu_insn;
		    default:
                	goto illegal_insn;
		}
#if defined(OPTIM)
	    } else if (xop == 0x2) {
		// clr/mov shortcut

                rs1 = GET_FIELD(insn, 13, 17);
		if (rs1 == 0) {
		    // or %g0, x, y -> mov T1, x; mov y, T1
		    if (IS_IMM) {	/* immediate */
			rs2 = GET_FIELDs(insn, 19, 31);
B
bellard 已提交
1736
			gen_movl_simm_T1(rs2);
B
bellard 已提交
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
		    } else {		/* register */
			rs2 = GET_FIELD(insn, 27, 31);
			gen_movl_reg_T1(rs2);
		    }
		    gen_movl_T1_reg(rd);
		} else {
		    gen_movl_reg_T0(rs1);
		    if (IS_IMM) {	/* immediate */
			// or x, #0, y -> mov T1, x; mov y, T1
			rs2 = GET_FIELDs(insn, 19, 31);
			if (rs2 != 0) {
B
bellard 已提交
1748
			    gen_movl_simm_T1(rs2);
B
bellard 已提交
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
			    gen_op_or_T1_T0();
			}
		    } else {		/* register */
			// or x, %g0, y -> mov T1, x; mov y, T1
			rs2 = GET_FIELD(insn, 27, 31);
			if (rs2 != 0) {
			    gen_movl_reg_T1(rs2);
			    gen_op_or_T1_T0();
			}
		    }
		    gen_movl_T0_reg(rd);
		}
B
bellard 已提交
1761 1762
#endif
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1763
	    } else if (xop == 0x25) { /* sll, V9 sllx */
B
bellard 已提交
1764 1765 1766 1767 1768 1769 1770 1771 1772
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
		if (IS_IMM) {	/* immediate */
                    rs2 = GET_FIELDs(insn, 20, 31);
                    gen_movl_simm_T1(rs2);
                } else {		/* register */
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
                }
B
blueswir1 已提交
1773 1774 1775 1776
		if (insn & (1 << 12))
		    gen_op_sllx();
		else
		    gen_op_sll();
B
bellard 已提交
1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807
		gen_movl_T0_reg(rd);
	    } else if (xop == 0x26) { /* srl, V9 srlx */
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
		if (IS_IMM) {	/* immediate */
                    rs2 = GET_FIELDs(insn, 20, 31);
                    gen_movl_simm_T1(rs2);
                } else {		/* register */
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
                }
		if (insn & (1 << 12))
		    gen_op_srlx();
		else
		    gen_op_srl();
		gen_movl_T0_reg(rd);
	    } else if (xop == 0x27) { /* sra, V9 srax */
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
		if (IS_IMM) {	/* immediate */
                    rs2 = GET_FIELDs(insn, 20, 31);
                    gen_movl_simm_T1(rs2);
                } else {		/* register */
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
                }
		if (insn & (1 << 12))
		    gen_op_srax();
		else
		    gen_op_sra();
		gen_movl_T0_reg(rd);
B
bellard 已提交
1808
#endif
1809
            } else if (xop < 0x36) {
B
bellard 已提交
1810 1811 1812
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
		if (IS_IMM) {	/* immediate */
1813
                    rs2 = GET_FIELDs(insn, 19, 31);
B
bellard 已提交
1814
                    gen_movl_simm_T1(rs2);
1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
                } else {		/* register */
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
                }
                if (xop < 0x20) {
                    switch (xop & ~0x10) {
                    case 0x0:
                        if (xop & 0x10)
                            gen_op_add_T1_T0_cc();
                        else
                            gen_op_add_T1_T0();
                        break;
                    case 0x1:
                        gen_op_and_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x2:
B
bellard 已提交
1833 1834 1835 1836
			gen_op_or_T1_T0();
			if (xop & 0x10)
			    gen_op_logic_T0_cc();
			break;
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864
                    case 0x3:
                        gen_op_xor_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x4:
                        if (xop & 0x10)
                            gen_op_sub_T1_T0_cc();
                        else
                            gen_op_sub_T1_T0();
                        break;
                    case 0x5:
                        gen_op_andn_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x6:
                        gen_op_orn_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x7:
                        gen_op_xnor_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x8:
                        if (xop & 0x10)
1865 1866 1867
                            gen_op_addx_T1_T0_cc();
                        else
                            gen_op_addx_T1_T0();
1868
                        break;
P
pbrook 已提交
1869 1870 1871 1872 1873
#ifdef TARGET_SPARC64
		    case 0x9: /* V9 mulx */
                        gen_op_mulx_T1_T0();
                        break;
#endif
1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885
                    case 0xa:
                        gen_op_umul_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0xb:
                        gen_op_smul_T1_T0();
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0xc:
                        if (xop & 0x10)
1886 1887 1888
                            gen_op_subx_T1_T0_cc();
                        else
                            gen_op_subx_T1_T0();
1889
                        break;
P
pbrook 已提交
1890 1891 1892 1893 1894
#ifdef TARGET_SPARC64
		    case 0xd: /* V9 udivx */
                        gen_op_udivx_T1_T0();
                        break;
#endif
1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907
                    case 0xe:
                        gen_op_udiv_T1_T0();
                        if (xop & 0x10)
                            gen_op_div_cc();
                        break;
                    case 0xf:
                        gen_op_sdiv_T1_T0();
                        if (xop & 0x10)
                            gen_op_div_cc();
                        break;
                    default:
                        goto illegal_insn;
                    }
B
bellard 已提交
1908
		    gen_movl_T0_reg(rd);
1909 1910
                } else {
                    switch (xop) {
B
bellard 已提交
1911
		    case 0x20: /* taddcc */
1912 1913 1914
			gen_op_tadd_T1_T0_cc();
		        gen_movl_T0_reg(rd);
			break;
B
bellard 已提交
1915
		    case 0x21: /* tsubcc */
1916 1917 1918
			gen_op_tsub_T1_T0_cc();
		        gen_movl_T0_reg(rd);
			break;
B
bellard 已提交
1919
		    case 0x22: /* taddcctv */
1920 1921 1922
			gen_op_tadd_T1_T0_ccTV();
		        gen_movl_T0_reg(rd);
			break;
B
bellard 已提交
1923
		    case 0x23: /* tsubcctv */
1924 1925 1926
			gen_op_tsub_T1_T0_ccTV();
		        gen_movl_T0_reg(rd);
			break;
1927 1928 1929 1930
                    case 0x24: /* mulscc */
                        gen_op_mulscc_T1_T0();
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1931 1932
#ifndef TARGET_SPARC64
                    case 0x25:	/* sll */
B
bellard 已提交
1933
			gen_op_sll();
1934 1935
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1936
                    case 0x26:  /* srl */
B
bellard 已提交
1937
			gen_op_srl();
1938 1939
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1940
                    case 0x27:  /* sra */
B
bellard 已提交
1941
			gen_op_sra();
1942 1943
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1944
#endif
1945 1946 1947
                    case 0x30:
                        {
                            switch(rd) {
B
bellard 已提交
1948 1949 1950
                            case 0: /* wry */
				gen_op_xor_T1_T0();
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1951
                                break;
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962
#ifndef TARGET_SPARC64
                            case 0x01 ... 0x0f: /* undefined in the
                                                   SPARCv8 manual, nop
                                                   on the microSPARC
                                                   II */
                            case 0x10 ... 0x1f: /* implementation-dependent
                                                   in the SPARCv8
                                                   manual, nop on the
                                                   microSPARC II */
                                break;
#else
1963
			    case 0x2: /* V9 wrccr */
B
bellard 已提交
1964 1965
                                gen_op_wrccr();
				break;
1966
			    case 0x3: /* V9 wrasi */
B
bellard 已提交
1967 1968
				gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
				break;
1969
			    case 0x6: /* V9 wrfprs */
1970
				gen_op_xor_T1_T0();
B
bellard 已提交
1971
				gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
1972 1973 1974 1975 1976
                                save_state(dc);
                                gen_op_next_insn();
                                gen_op_movl_T0_0();
                                gen_op_exit_tb();
                                dc->is_br = 1;
B
bellard 已提交
1977 1978 1979 1980 1981 1982 1983
				break;
			    case 0xf: /* V9 sir, nop if user */
#if !defined(CONFIG_USER_ONLY)
				if (supervisor(dc))
				    gen_op_sir();
#endif
				break;
B
bellard 已提交
1984 1985 1986 1987 1988
			    case 0x13: /* Graphics Status */
                                if (gen_trap_ifnofpu(dc))
                                    goto jmp_insn;
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
				break;
B
bellard 已提交
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
			    case 0x17: /* Tick compare */
#if !defined(CONFIG_USER_ONLY)
				if (!supervisor(dc))
				    goto illegal_insn;
#endif
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
				break;
			    case 0x18: /* System tick */
#if !defined(CONFIG_USER_ONLY)
				if (!supervisor(dc))
				    goto illegal_insn;
#endif
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
				break;
			    case 0x19: /* System tick compare */
#if !defined(CONFIG_USER_ONLY)
				if (!supervisor(dc))
				    goto illegal_insn;
B
bellard 已提交
2007
#endif
B
bellard 已提交
2008 2009 2010
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
				break;

B
bellard 已提交
2011 2012 2013 2014 2015 2016
			    case 0x10: /* Performance Control */
			    case 0x11: /* Performance Instrumentation Counter */
			    case 0x12: /* Dispatch Control */
			    case 0x14: /* Softint set */
			    case 0x15: /* Softint clear */
			    case 0x16: /* Softint write */
B
bellard 已提交
2017
#endif
B
bellard 已提交
2018
                            default:
2019 2020 2021 2022
                                goto illegal_insn;
                            }
                        }
                        break;
2023
#if !defined(CONFIG_USER_ONLY)
2024
                    case 0x31: /* wrpsr, V9 saved, restored */
2025 2026 2027
                        {
			    if (!supervisor(dc))
				goto priv_insn;
B
bellard 已提交
2028 2029 2030 2031 2032 2033 2034 2035
#ifdef TARGET_SPARC64
			    switch (rd) {
			    case 0:
				gen_op_saved();
				break;
			    case 1:
				gen_op_restored();
				break;
B
blueswir1 已提交
2036 2037 2038 2039 2040
                            case 2: /* UA2005 allclean */
                            case 3: /* UA2005 otherw */
                            case 4: /* UA2005 normalw */
                            case 5: /* UA2005 invalw */
                                // XXX
B
bellard 已提交
2041 2042 2043 2044
			    default:
                                goto illegal_insn;
                            }
#else
2045 2046
                            gen_op_xor_T1_T0();
                            gen_op_wrpsr();
B
bellard 已提交
2047 2048 2049 2050 2051
                            save_state(dc);
                            gen_op_next_insn();
			    gen_op_movl_T0_0();
			    gen_op_exit_tb();
			    dc->is_br = 1;
B
bellard 已提交
2052
#endif
2053 2054
                        }
                        break;
2055
                    case 0x32: /* wrwim, V9 wrpr */
2056 2057 2058 2059
                        {
			    if (!supervisor(dc))
				goto priv_insn;
                            gen_op_xor_T1_T0();
B
bellard 已提交
2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077
#ifdef TARGET_SPARC64
			    switch (rd) {
			    case 0: // tpc
				gen_op_wrtpc();
				break;
			    case 1: // tnpc
				gen_op_wrtnpc();
				break;
			    case 2: // tstate
				gen_op_wrtstate();
				break;
			    case 3: // tt
				gen_op_wrtt();
				break;
			    case 4: // tick
				gen_op_wrtick();
				break;
			    case 5: // tba
B
bellard 已提交
2078
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
B
bellard 已提交
2079 2080 2081
				break;
			    case 6: // pstate
				gen_op_wrpstate();
P
pbrook 已提交
2082 2083 2084 2085 2086
                                save_state(dc);
                                gen_op_next_insn();
                                gen_op_movl_T0_0();
                                gen_op_exit_tb();
                                dc->is_br = 1;
B
bellard 已提交
2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111
				break;
			    case 7: // tl
				gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
				break;
			    case 8: // pil
				gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
				break;
			    case 9: // cwp
				gen_op_wrcwp();
				break;
			    case 10: // cansave
				gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
				break;
			    case 11: // canrestore
				gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
				break;
			    case 12: // cleanwin
				gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
				break;
			    case 13: // otherwin
				gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
				break;
			    case 14: // wstate
				gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
				break;
B
blueswir1 已提交
2112 2113 2114 2115 2116 2117 2118 2119
                            case 16: // UA2005 gl
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, gl));
                                break;
                            case 26: // UA2005 strand status
                                if (!hypervisor(dc))
                                    goto priv_insn;
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, ssr));
                                break;
B
bellard 已提交
2120 2121 2122 2123
			    default:
				goto illegal_insn;
			    }
#else
B
bellard 已提交
2124
			    gen_op_wrwim();
B
bellard 已提交
2125
#endif
2126 2127
                        }
                        break;
B
blueswir1 已提交
2128
                    case 0x33: /* wrtbr, UA2005 wrhpr */
2129
                        {
B
blueswir1 已提交
2130
#ifndef TARGET_SPARC64
2131 2132 2133
			    if (!supervisor(dc))
				goto priv_insn;
                            gen_op_xor_T1_T0();
B
blueswir1 已提交
2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164
                            gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
#else
                            if (!hypervisor(dc))
                                goto priv_insn;
                            gen_op_xor_T1_T0();
                            switch (rd) {
                            case 0: // hpstate
                                // XXX gen_op_wrhpstate();
                                save_state(dc);
                                gen_op_next_insn();
                                gen_op_movl_T0_0();
                                gen_op_exit_tb();
                                dc->is_br = 1;
                                break;
                            case 1: // htstate
                                // XXX gen_op_wrhtstate();
                                break;
                            case 3: // hintp
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, hintp));
                                break;
                            case 5: // htba
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
                                break;
                            case 31: // hstick_cmpr
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
                                break;
                            case 6: // hver readonly
                            default:
                                goto illegal_insn;
                            }
#endif
2165 2166 2167
                        }
                        break;
#endif
B
bellard 已提交
2168
#ifdef TARGET_SPARC64
2169
		    case 0x2c: /* V9 movcc */
B
bellard 已提交
2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196
			{
			    int cc = GET_FIELD_SP(insn, 11, 12);
			    int cond = GET_FIELD_SP(insn, 14, 17);
			    if (IS_IMM) {	/* immediate */
				rs2 = GET_FIELD_SPs(insn, 0, 10);
				gen_movl_simm_T1(rs2);
			    }
			    else {
				rs2 = GET_FIELD_SP(insn, 0, 4);
				gen_movl_reg_T1(rs2);
			    }
			    gen_movl_reg_T0(rd);
			    flush_T2(dc);
			    if (insn & (1 << 18)) {
				if (cc == 0)
				    gen_cond[0][cond]();
				else if (cc == 2)
				    gen_cond[1][cond]();
				else
				    goto illegal_insn;
			    } else {
				gen_fcond[cc][cond]();
			    }
			    gen_op_mov_cc();
			    gen_movl_T0_reg(rd);
			    break;
			}
2197
		    case 0x2d: /* V9 sdivx */
B
bellard 已提交
2198 2199 2200
                        gen_op_sdivx_T1_T0();
			gen_movl_T0_reg(rd);
                        break;
2201
		    case 0x2e: /* V9 popc */
B
bellard 已提交
2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214
			{
			    if (IS_IMM) {	/* immediate */
				rs2 = GET_FIELD_SPs(insn, 0, 12);
				gen_movl_simm_T1(rs2);
				// XXX optimize: popc(constant)
			    }
			    else {
				rs2 = GET_FIELD_SP(insn, 0, 4);
				gen_movl_reg_T1(rs2);
			    }
			    gen_op_popc();
			    gen_movl_T0_reg(rd);
			}
2215
		    case 0x2f: /* V9 movr */
B
bellard 已提交
2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
			{
			    int cond = GET_FIELD_SP(insn, 10, 12);
			    rs1 = GET_FIELD(insn, 13, 17);
			    flush_T2(dc);
			    gen_movl_reg_T0(rs1);
			    gen_cond_reg(cond);
			    if (IS_IMM) {	/* immediate */
				rs2 = GET_FIELD_SPs(insn, 0, 10);
				gen_movl_simm_T1(rs2);
			    }
			    else {
				rs2 = GET_FIELD_SP(insn, 0, 4);
				gen_movl_reg_T1(rs2);
			    }
			    gen_movl_reg_T0(rd);
			    gen_op_mov_cc();
			    gen_movl_T0_reg(rd);
			    break;
			}
#endif
		    default:
B
bellard 已提交
2237 2238 2239
			goto illegal_insn;
		    }
		}
2240 2241 2242 2243 2244
            } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
#ifdef TARGET_SPARC64
                int opf = GET_FIELD_SP(insn, 5, 13);
                rs1 = GET_FIELD(insn, 13, 17);
                rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
2245 2246
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
2247 2248

                switch (opf) {
B
blueswir1 已提交
2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280
                case 0x000: /* VIS I edge8cc */
                case 0x001: /* VIS II edge8n */
                case 0x002: /* VIS I edge8lcc */
                case 0x003: /* VIS II edge8ln */
                case 0x004: /* VIS I edge16cc */
                case 0x005: /* VIS II edge16n */
                case 0x006: /* VIS I edge16lcc */
                case 0x007: /* VIS II edge16ln */
                case 0x008: /* VIS I edge32cc */
                case 0x009: /* VIS II edge32n */
                case 0x00a: /* VIS I edge32lcc */
                case 0x00b: /* VIS II edge32ln */
                    // XXX
                    goto illegal_insn;
                case 0x010: /* VIS I array8 */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_array8();
                    gen_movl_T0_reg(rd);
                    break;
                case 0x012: /* VIS I array16 */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_array16();
                    gen_movl_T0_reg(rd);
                    break;
                case 0x014: /* VIS I array32 */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_array32();
                    gen_movl_T0_reg(rd);
                    break;
2281 2282 2283 2284 2285 2286
                case 0x018: /* VIS I alignaddr */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_alignaddr();
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
2287
                case 0x019: /* VIS II bmask */
2288 2289
                case 0x01a: /* VIS I alignaddrl */
                    // XXX
B
blueswir1 已提交
2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
                    goto illegal_insn;
                case 0x020: /* VIS I fcmple16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmple16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x022: /* VIS I fcmpne16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmpne16();
                    gen_op_store_DT0_fpr(rd);
2302
                    break;
B
blueswir1 已提交
2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
                case 0x024: /* VIS I fcmple32 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmple32();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x026: /* VIS I fcmpne32 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmpne32();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x028: /* VIS I fcmpgt16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmpgt16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x02a: /* VIS I fcmpeq16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmpeq16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x02c: /* VIS I fcmpgt32 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmpgt32();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x02e: /* VIS I fcmpeq32 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fcmpeq32();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x031: /* VIS I fmul8x16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmul8x16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x033: /* VIS I fmul8x16au */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmul8x16au();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x035: /* VIS I fmul8x16al */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmul8x16al();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x036: /* VIS I fmul8sux16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmul8sux16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x037: /* VIS I fmul8ulx16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmul8ulx16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x038: /* VIS I fmuld8sux16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmuld8sux16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x039: /* VIS I fmuld8ulx16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fmuld8ulx16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x03a: /* VIS I fpack32 */
                case 0x03b: /* VIS I fpack16 */
                case 0x03d: /* VIS I fpackfix */
                case 0x03e: /* VIS I pdist */
                    // XXX
                    goto illegal_insn;
2387 2388 2389 2390 2391 2392
                case 0x048: /* VIS I faligndata */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_faligndata();
                    gen_op_store_DT0_fpr(rd);
                    break;
B
blueswir1 已提交
2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455
                case 0x04b: /* VIS I fpmerge */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fpmerge();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x04c: /* VIS II bshuffle */
                    // XXX
                    goto illegal_insn;
                case 0x04d: /* VIS I fexpand */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fexpand();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x050: /* VIS I fpadd16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fpadd16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x051: /* VIS I fpadd16s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpadd16s();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x052: /* VIS I fpadd32 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fpadd32();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x053: /* VIS I fpadd32s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpadd32s();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x054: /* VIS I fpsub16 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fpsub16();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x055: /* VIS I fpsub16s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpsub16s();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x056: /* VIS I fpsub32 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fpadd32();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x057: /* VIS I fpsub32s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpsub32s();
                    gen_op_store_FT0_fpr(rd);
                    break;
2456 2457 2458 2459 2460 2461 2462 2463
                case 0x060: /* VIS I fzero */
                    gen_op_movl_DT0_0();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x061: /* VIS I fzeros */
                    gen_op_movl_FT0_0();
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
                case 0x062: /* VIS I fnor */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fnor();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x063: /* VIS I fnors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fnors();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x064: /* VIS I fandnot2 */
                    gen_op_load_fpr_DT1(rs1);
                    gen_op_load_fpr_DT0(rs2);
                    gen_op_fandnot();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x065: /* VIS I fandnot2s */
                    gen_op_load_fpr_FT1(rs1);
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_fandnots();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x066: /* VIS I fnot2 */
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fnot();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x067: /* VIS I fnot2s */
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fnot();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x068: /* VIS I fandnot1 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fandnot();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x069: /* VIS I fandnot1s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fandnots();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x06a: /* VIS I fnot1 */
                    gen_op_load_fpr_DT1(rs1);
                    gen_op_fnot();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x06b: /* VIS I fnot1s */
                    gen_op_load_fpr_FT1(rs1);
                    gen_op_fnot();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x06c: /* VIS I fxor */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fxor();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x06d: /* VIS I fxors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fxors();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x06e: /* VIS I fnand */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fnand();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x06f: /* VIS I fnands */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fnands();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x070: /* VIS I fand */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fand();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x071: /* VIS I fands */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fands();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x072: /* VIS I fxnor */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fxnor();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x073: /* VIS I fxnors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fxnors();
                    gen_op_store_FT0_fpr(rd);
                    break;
2568 2569 2570 2571 2572 2573 2574 2575
                case 0x074: /* VIS I fsrc1 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x075: /* VIS I fsrc1s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587
                case 0x076: /* VIS I fornot2 */
                    gen_op_load_fpr_DT1(rs1);
                    gen_op_load_fpr_DT0(rs2);
                    gen_op_fornot();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x077: /* VIS I fornot2s */
                    gen_op_load_fpr_FT1(rs1);
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_fornots();
                    gen_op_store_FT0_fpr(rd);
                    break;
2588 2589 2590 2591 2592 2593 2594 2595
                case 0x078: /* VIS I fsrc2 */
                    gen_op_load_fpr_DT0(rs2);
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x079: /* VIS I fsrc2s */
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619
                case 0x07a: /* VIS I fornot1 */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_fornot();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x07b: /* VIS I fornot1s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fornots();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x07c: /* VIS I for */
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_for();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x07d: /* VIS I fors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fors();
                    gen_op_store_FT0_fpr(rd);
                    break;
2620 2621 2622 2623 2624 2625 2626 2627
                case 0x07e: /* VIS I fone */
                    gen_op_movl_DT0_1();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x07f: /* VIS I fones */
                    gen_op_movl_FT0_1();
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
2628 2629 2630 2631
                case 0x080: /* VIS I shutdown */
                case 0x081: /* VIS II siam */
                    // XXX
                    goto illegal_insn;
2632 2633 2634 2635 2636 2637 2638
                default:
                    goto illegal_insn;
                }
#else
	        goto ncp_insn;
#endif
            } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
2639 2640 2641 2642 2643
#ifdef TARGET_SPARC64
	        goto illegal_insn;
#else
	        goto ncp_insn;
#endif
B
bellard 已提交
2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668
#ifdef TARGET_SPARC64
	    } else if (xop == 0x39) { /* V9 return */
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
                if (IS_IMM) {	/* immediate */
		    rs2 = GET_FIELDs(insn, 19, 31);
#if defined(OPTIM)
		    if (rs2) {
#endif
			gen_movl_simm_T1(rs2);
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
#endif
                } else {		/* register */
                    rs2 = GET_FIELD(insn, 27, 31);
#if defined(OPTIM)
		    if (rs2) {
#endif
			gen_movl_reg_T1(rs2);
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
#endif
                }
B
bellard 已提交
2669
		gen_op_restore();
B
bellard 已提交
2670 2671 2672 2673 2674
		gen_mov_pc_npc(dc);
		gen_op_movl_npc_T0();
		dc->npc = DYNAMIC_PC;
		goto jmp_insn;
#endif
B
bellard 已提交
2675 2676 2677 2678 2679 2680 2681
	    } else {
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
                if (IS_IMM) {	/* immediate */
		    rs2 = GET_FIELDs(insn, 19, 31);
#if defined(OPTIM)
		    if (rs2) {
2682
#endif
B
bellard 已提交
2683
			gen_movl_simm_T1(rs2);
B
bellard 已提交
2684 2685 2686
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
2687
#endif
B
bellard 已提交
2688 2689 2690 2691 2692 2693 2694 2695 2696
                } else {		/* register */
                    rs2 = GET_FIELD(insn, 27, 31);
#if defined(OPTIM)
		    if (rs2) {
#endif
			gen_movl_reg_T1(rs2);
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
2697
#endif
2698
                }
B
bellard 已提交
2699 2700 2701 2702
		switch (xop) {
		case 0x38:	/* jmpl */
		    {
			if (rd != 0) {
P
pbrook 已提交
2703 2704 2705 2706 2707 2708 2709
#ifdef TARGET_SPARC64
                            if (dc->pc == (uint32_t)dc->pc) {
                                gen_op_movl_T1_im(dc->pc);
                            } else {
                                gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
                            }
#else
B
bellard 已提交
2710
			    gen_op_movl_T1_im(dc->pc);
P
pbrook 已提交
2711
#endif
B
bellard 已提交
2712
			    gen_movl_T1_reg(rd);
B
bellard 已提交
2713
			}
B
bellard 已提交
2714 2715
                        gen_mov_pc_npc(dc);
			gen_op_movl_npc_T0();
B
bellard 已提交
2716 2717 2718
			dc->npc = DYNAMIC_PC;
		    }
		    goto jmp_insn;
B
bellard 已提交
2719
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2720
		case 0x39:	/* rett, V9 return */
B
bellard 已提交
2721 2722 2723
		    {
			if (!supervisor(dc))
			    goto priv_insn;
B
bellard 已提交
2724
                        gen_mov_pc_npc(dc);
B
bellard 已提交
2725
			gen_op_movl_npc_T0();
B
bellard 已提交
2726
			dc->npc = DYNAMIC_PC;
B
bellard 已提交
2727 2728
			gen_op_rett();
		    }
B
bellard 已提交
2729
		    goto jmp_insn;
B
bellard 已提交
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743
#endif
		case 0x3b: /* flush */
		    gen_op_flush_T0();
		    break;
		case 0x3c:	/* save */
		    save_state(dc);
		    gen_op_save();
		    gen_movl_T0_reg(rd);
		    break;
		case 0x3d:	/* restore */
		    save_state(dc);
		    gen_op_restore();
		    gen_movl_T0_reg(rd);
		    break;
B
bellard 已提交
2744
#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
2745
		case 0x3e:      /* V9 done/retry */
B
bellard 已提交
2746 2747 2748 2749 2750
		    {
			switch (rd) {
			case 0:
			    if (!supervisor(dc))
				goto priv_insn;
B
bellard 已提交
2751 2752
			    dc->npc = DYNAMIC_PC;
			    dc->pc = DYNAMIC_PC;
B
bellard 已提交
2753
			    gen_op_done();
B
bellard 已提交
2754
			    goto jmp_insn;
B
bellard 已提交
2755 2756 2757
			case 1:
			    if (!supervisor(dc))
				goto priv_insn;
B
bellard 已提交
2758 2759
			    dc->npc = DYNAMIC_PC;
			    dc->pc = DYNAMIC_PC;
B
bellard 已提交
2760
			    gen_op_retry();
B
bellard 已提交
2761
			    goto jmp_insn;
B
bellard 已提交
2762 2763 2764 2765 2766 2767 2768
			default:
			    goto illegal_insn;
			}
		    }
		    break;
#endif
		default:
B
bellard 已提交
2769 2770
		    goto illegal_insn;
		}
2771 2772 2773
            }
	    break;
	}
2774
	break;
2775 2776 2777 2778 2779 2780 2781
    case 3:			/* load/store instructions */
	{
	    unsigned int xop = GET_FIELD(insn, 7, 12);
	    rs1 = GET_FIELD(insn, 13, 17);
	    gen_movl_reg_T0(rs1);
	    if (IS_IMM) {	/* immediate */
		rs2 = GET_FIELDs(insn, 19, 31);
B
bellard 已提交
2782
#if defined(OPTIM)
2783
		if (rs2 != 0) {
B
bellard 已提交
2784
#endif
B
bellard 已提交
2785
		    gen_movl_simm_T1(rs2);
2786
		    gen_op_add_T1_T0();
B
bellard 已提交
2787
#if defined(OPTIM)
2788
		}
B
bellard 已提交
2789
#endif
2790 2791
	    } else {		/* register */
		rs2 = GET_FIELD(insn, 27, 31);
B
bellard 已提交
2792 2793 2794 2795 2796 2797 2798 2799
#if defined(OPTIM)
		if (rs2 != 0) {
#endif
		    gen_movl_reg_T1(rs2);
		    gen_op_add_T1_T0();
#if defined(OPTIM)
		}
#endif
2800
	    }
B
bellard 已提交
2801
	    if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
B
blueswir1 已提交
2802 2803
		    (xop > 0x17 && xop <= 0x1d ) || \
		    (xop > 0x2c && xop <= 0x33) || xop == 0x1f) {
2804 2805
		switch (xop) {
		case 0x0:	/* load word */
2806
		    gen_op_ldst(ld);
2807 2808
		    break;
		case 0x1:	/* load unsigned byte */
2809
		    gen_op_ldst(ldub);
2810 2811
		    break;
		case 0x2:	/* load unsigned halfword */
2812
		    gen_op_ldst(lduh);
2813 2814
		    break;
		case 0x3:	/* load double word */
2815 2816
		    if (rd & 1)
                        goto illegal_insn;
2817
		    gen_op_ldst(ldd);
2818 2819 2820
		    gen_movl_T0_reg(rd + 1);
		    break;
		case 0x9:	/* load signed byte */
2821
		    gen_op_ldst(ldsb);
2822 2823
		    break;
		case 0xa:	/* load signed halfword */
2824
		    gen_op_ldst(ldsh);
2825 2826
		    break;
		case 0xd:	/* ldstub -- XXX: should be atomically */
2827
		    gen_op_ldst(ldstub);
2828 2829
		    break;
		case 0x0f:	/* swap register with memory. Also atomically */
B
bellard 已提交
2830
		    gen_movl_reg_T1(rd);
2831 2832
		    gen_op_ldst(swap);
		    break;
B
bellard 已提交
2833
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2834
		case 0x10:	/* load word alternate */
B
bellard 已提交
2835
#ifndef TARGET_SPARC64
2836 2837
		    if (IS_IMM)
			goto illegal_insn;
2838 2839
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2840
#endif
2841 2842 2843
		    gen_op_lda(insn, 1, 4, 0);
		    break;
		case 0x11:	/* load unsigned byte alternate */
B
bellard 已提交
2844
#ifndef TARGET_SPARC64
2845 2846
		    if (IS_IMM)
			goto illegal_insn;
2847 2848
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2849
#endif
2850 2851 2852
		    gen_op_lduba(insn, 1, 1, 0);
		    break;
		case 0x12:	/* load unsigned halfword alternate */
B
bellard 已提交
2853
#ifndef TARGET_SPARC64
2854 2855
		    if (IS_IMM)
			goto illegal_insn;
2856 2857
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2858
#endif
2859 2860 2861
		    gen_op_lduha(insn, 1, 2, 0);
		    break;
		case 0x13:	/* load double word alternate */
B
bellard 已提交
2862
#ifndef TARGET_SPARC64
2863 2864
		    if (IS_IMM)
			goto illegal_insn;
2865 2866
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2867
#endif
2868 2869
		    if (rd & 1)
                        goto illegal_insn;
2870 2871 2872 2873
		    gen_op_ldda(insn, 1, 8, 0);
		    gen_movl_T0_reg(rd + 1);
		    break;
		case 0x19:	/* load signed byte alternate */
B
bellard 已提交
2874
#ifndef TARGET_SPARC64
2875 2876
		    if (IS_IMM)
			goto illegal_insn;
2877 2878
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2879
#endif
2880 2881 2882
		    gen_op_ldsba(insn, 1, 1, 1);
		    break;
		case 0x1a:	/* load signed halfword alternate */
B
bellard 已提交
2883
#ifndef TARGET_SPARC64
2884 2885
		    if (IS_IMM)
			goto illegal_insn;
2886 2887
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2888
#endif
2889 2890 2891
		    gen_op_ldsha(insn, 1, 2 ,1);
		    break;
		case 0x1d:	/* ldstuba -- XXX: should be atomically */
B
bellard 已提交
2892
#ifndef TARGET_SPARC64
2893 2894
		    if (IS_IMM)
			goto illegal_insn;
2895 2896
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2897
#endif
2898 2899 2900
		    gen_op_ldstuba(insn, 1, 1, 0);
		    break;
		case 0x1f:	/* swap reg with alt. memory. Also atomically */
B
bellard 已提交
2901
#ifndef TARGET_SPARC64
2902 2903
		    if (IS_IMM)
			goto illegal_insn;
2904 2905
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2906
#endif
B
bellard 已提交
2907
		    gen_movl_reg_T1(rd);
2908
		    gen_op_swapa(insn, 1, 4, 0);
2909
		    break;
B
bellard 已提交
2910 2911

#ifndef TARGET_SPARC64
2912 2913 2914 2915
		case 0x30: /* ldc */
		case 0x31: /* ldcsr */
		case 0x33: /* lddc */
		    goto ncp_insn;
B
bellard 已提交
2916 2917 2918 2919 2920
                    /* avoid warnings */
                    (void) &gen_op_stfa;
                    (void) &gen_op_stdfa;
                    (void) &gen_op_ldfa;
                    (void) &gen_op_lddfa;
B
bellard 已提交
2921 2922 2923 2924
#else
#if !defined(CONFIG_USER_ONLY)
		    (void) &gen_op_cas;
		    (void) &gen_op_casx;
B
bellard 已提交
2925
#endif
B
bellard 已提交
2926 2927 2928
#endif
#endif
#ifdef TARGET_SPARC64
2929
		case 0x08: /* V9 ldsw */
B
bellard 已提交
2930 2931
		    gen_op_ldst(ldsw);
		    break;
2932
		case 0x0b: /* V9 ldx */
B
bellard 已提交
2933 2934
		    gen_op_ldst(ldx);
		    break;
2935
		case 0x18: /* V9 ldswa */
B
bellard 已提交
2936 2937
		    gen_op_ldswa(insn, 1, 4, 1);
		    break;
2938
		case 0x1b: /* V9 ldxa */
B
bellard 已提交
2939 2940 2941 2942
		    gen_op_ldxa(insn, 1, 8, 0);
		    break;
		case 0x2d: /* V9 prefetch, no effect */
		    goto skip_move;
2943
		case 0x30: /* V9 ldfa */
B
bellard 已提交
2944 2945
		    gen_op_ldfa(insn, 1, 8, 0); // XXX
		    break;
2946
		case 0x33: /* V9 lddfa */
B
bellard 已提交
2947
		    gen_op_lddfa(insn, 1, 8, 0); // XXX
2948

B
bellard 已提交
2949 2950 2951
		    break;
		case 0x3d: /* V9 prefetcha, no effect */
		    goto skip_move;
2952
		case 0x32: /* V9 ldqfa */
B
bellard 已提交
2953 2954 2955
		    goto nfpu_insn;
#endif
		default:
B
bellard 已提交
2956
		    goto illegal_insn;
2957
		}
2958
		gen_movl_T1_reg(rd);
B
bellard 已提交
2959 2960 2961
#ifdef TARGET_SPARC64
	    skip_move: ;
#endif
2962
	    } else if (xop >= 0x20 && xop < 0x24) {
B
bellard 已提交
2963 2964
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
2965 2966 2967 2968 2969 2970
		switch (xop) {
		case 0x20:	/* load fpreg */
		    gen_op_ldst(ldf);
		    gen_op_store_FT0_fpr(rd);
		    break;
		case 0x21:	/* load fsr */
B
bellard 已提交
2971
		    gen_op_ldst(ldf);
2972 2973
		    gen_op_ldfsr();
		    break;
2974 2975
		case 0x22:      /* load quad fpreg */
		    goto nfpu_insn;
2976 2977
		case 0x23:	/* load double fpreg */
		    gen_op_ldst(lddf);
B
bellard 已提交
2978
		    gen_op_store_DT0_fpr(DFPREG(rd));
2979
		    break;
B
bellard 已提交
2980 2981
		default:
		    goto illegal_insn;
2982
		}
B
bellard 已提交
2983 2984
	    } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
		       xop == 0xe || xop == 0x1e) {
2985 2986 2987
		gen_movl_reg_T1(rd);
		switch (xop) {
		case 0x4:
2988
		    gen_op_ldst(st);
2989 2990
		    break;
		case 0x5:
2991
		    gen_op_ldst(stb);
2992 2993
		    break;
		case 0x6:
2994
		    gen_op_ldst(sth);
2995 2996
		    break;
		case 0x7:
2997 2998
		    if (rd & 1)
                        goto illegal_insn;
B
bellard 已提交
2999
                    flush_T2(dc);
3000
		    gen_movl_reg_T2(rd + 1);
3001 3002
		    gen_op_ldst(std);
		    break;
B
bellard 已提交
3003
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
3004
		case 0x14:
B
bellard 已提交
3005
#ifndef TARGET_SPARC64
3006 3007
		    if (IS_IMM)
			goto illegal_insn;
3008 3009
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
3010
#endif
3011
		    gen_op_sta(insn, 0, 4, 0);
B
bellard 已提交
3012
                    break;
3013
		case 0x15:
B
bellard 已提交
3014
#ifndef TARGET_SPARC64
3015 3016
		    if (IS_IMM)
			goto illegal_insn;
3017 3018
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
3019
#endif
3020
		    gen_op_stba(insn, 0, 1, 0);
B
bellard 已提交
3021
                    break;
3022
		case 0x16:
B
bellard 已提交
3023
#ifndef TARGET_SPARC64
3024 3025
		    if (IS_IMM)
			goto illegal_insn;
3026 3027
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
3028
#endif
3029
		    gen_op_stha(insn, 0, 2, 0);
B
bellard 已提交
3030
                    break;
3031
		case 0x17:
B
bellard 已提交
3032
#ifndef TARGET_SPARC64
3033 3034
		    if (IS_IMM)
			goto illegal_insn;
3035 3036
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
3037
#endif
3038 3039
		    if (rd & 1)
                        goto illegal_insn;
3040 3041 3042
                    flush_T2(dc);
		    gen_movl_reg_T2(rd + 1);
		    gen_op_stda(insn, 0, 8, 0);
B
bellard 已提交
3043
                    break;
B
bellard 已提交
3044
#endif
B
bellard 已提交
3045
#ifdef TARGET_SPARC64
3046
		case 0x0e: /* V9 stx */
B
bellard 已提交
3047 3048
		    gen_op_ldst(stx);
		    break;
3049
		case 0x1e: /* V9 stxa */
B
bellard 已提交
3050 3051 3052 3053
		    gen_op_stxa(insn, 0, 8, 0); // XXX
		    break;
#endif
		default:
B
bellard 已提交
3054
		    goto illegal_insn;
3055
		}
3056
	    } else if (xop > 0x23 && xop < 0x28) {
B
bellard 已提交
3057 3058
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
3059 3060 3061 3062 3063
		switch (xop) {
		case 0x24:
                    gen_op_load_fpr_FT0(rd);
		    gen_op_ldst(stf);
		    break;
3064
		case 0x25: /* stfsr, V9 stxfsr */
3065
		    gen_op_stfsr();
B
bellard 已提交
3066
		    gen_op_ldst(stf);
3067
		    break;
B
blueswir1 已提交
3068
#if !defined(CONFIG_USER_ONLY)
3069
		case 0x26: /* stdfq */
B
blueswir1 已提交
3070 3071 3072 3073 3074 3075
		    if (!supervisor(dc))
			goto priv_insn;
		    if (gen_trap_ifnofpu(dc))
			goto jmp_insn;
		    goto nfq_insn;
#endif
3076
		case 0x27:
B
bellard 已提交
3077
                    gen_op_load_fpr_DT0(DFPREG(rd));
3078 3079
		    gen_op_ldst(stdf);
		    break;
B
bellard 已提交
3080
		default:
B
bellard 已提交
3081 3082 3083 3084
		    goto illegal_insn;
		}
	    } else if (xop > 0x33 && xop < 0x3f) {
		switch (xop) {
3085
#ifdef TARGET_SPARC64
3086
		case 0x34: /* V9 stfa */
B
bellard 已提交
3087 3088
		    gen_op_stfa(insn, 0, 0, 0); // XXX
		    break;
3089
		case 0x37: /* V9 stdfa */
B
bellard 已提交
3090 3091
		    gen_op_stdfa(insn, 0, 0, 0); // XXX
		    break;
3092
		case 0x3c: /* V9 casa */
B
bellard 已提交
3093 3094
		    gen_op_casa(insn, 0, 4, 0); // XXX
		    break;
3095
		case 0x3e: /* V9 casxa */
B
bellard 已提交
3096 3097
		    gen_op_casxa(insn, 0, 8, 0); // XXX
		    break;
3098
		case 0x36: /* V9 stqfa */
B
bellard 已提交
3099
		    goto nfpu_insn;
3100 3101 3102 3103 3104 3105 3106
#else
		case 0x34: /* stc */
		case 0x35: /* stcsr */
		case 0x36: /* stdcq */
		case 0x37: /* stdc */
		    goto ncp_insn;
#endif
B
bellard 已提交
3107
		default:
B
bellard 已提交
3108
		    goto illegal_insn;
3109 3110
		}
            }
B
bellard 已提交
3111 3112
	    else
		goto illegal_insn;
3113
	}
3114
	break;
3115 3116
    }
    /* default case for non jump instructions */
B
bellard 已提交
3117 3118 3119 3120 3121
    if (dc->npc == DYNAMIC_PC) {
	dc->pc = DYNAMIC_PC;
	gen_op_next_insn();
    } else if (dc->npc == JUMP_PC) {
        /* we can do a static jump */
B
bellard 已提交
3122
        gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
3123 3124
        dc->is_br = 1;
    } else {
3125 3126 3127
	dc->pc = dc->npc;
	dc->npc = dc->npc + 4;
    }
B
bellard 已提交
3128
 jmp_insn:
3129 3130
    return;
 illegal_insn:
B
bellard 已提交
3131
    save_state(dc);
3132 3133
    gen_op_exception(TT_ILL_INSN);
    dc->is_br = 1;
3134
    return;
B
bellard 已提交
3135
#if !defined(CONFIG_USER_ONLY)
3136 3137 3138 3139
 priv_insn:
    save_state(dc);
    gen_op_exception(TT_PRIV_INSN);
    dc->is_br = 1;
B
bellard 已提交
3140 3141 3142 3143 3144 3145
    return;
#endif
 nfpu_insn:
    save_state(dc);
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
    dc->is_br = 1;
3146
    return;
B
blueswir1 已提交
3147 3148 3149 3150 3151 3152 3153
#if !defined(CONFIG_USER_ONLY)
 nfq_insn:
    save_state(dc);
    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
    dc->is_br = 1;
    return;
#endif
3154 3155 3156 3157 3158 3159 3160
#ifndef TARGET_SPARC64
 ncp_insn:
    save_state(dc);
    gen_op_exception(TT_NCP_INSN);
    dc->is_br = 1;
    return;
#endif
3161 3162
}

3163
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
3164
						 int spc, CPUSPARCState *env)
3165
{
B
bellard 已提交
3166
    target_ulong pc_start, last_pc;
3167 3168
    uint16_t *gen_opc_end;
    DisasContext dc1, *dc = &dc1;
3169
    int j, lj = -1;
3170 3171 3172

    memset(dc, 0, sizeof(DisasContext));
    dc->tb = tb;
B
bellard 已提交
3173
    pc_start = tb->pc;
3174
    dc->pc = pc_start;
B
bellard 已提交
3175
    last_pc = dc->pc;
B
bellard 已提交
3176
    dc->npc = (target_ulong) tb->cs_base;
3177 3178
#if defined(CONFIG_USER_ONLY)
    dc->mem_idx = 0;
B
bellard 已提交
3179
    dc->fpu_enabled = 1;
3180 3181
#else
    dc->mem_idx = ((env->psrs) != 0);
B
bellard 已提交
3182 3183 3184 3185 3186
#ifdef TARGET_SPARC64
    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
#else
    dc->fpu_enabled = ((env->psref) != 0);
#endif
3187
#endif
3188 3189 3190
    gen_opc_ptr = gen_opc_buf;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
    gen_opparam_ptr = gen_opparam_buf;
B
bellard 已提交
3191
    nb_gen_labels = 0;
3192 3193

    do {
3194 3195 3196
        if (env->nb_breakpoints > 0) {
            for(j = 0; j < env->nb_breakpoints; j++) {
                if (env->breakpoints[j] == dc->pc) {
B
bellard 已提交
3197 3198 3199 3200 3201 3202 3203
		    if (dc->pc != pc_start)
			save_state(dc);
                    gen_op_debug();
		    gen_op_movl_T0_0();
		    gen_op_exit_tb();
		    dc->is_br = 1;
                    goto exit_gen_loop;
3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219
                }
            }
        }
        if (spc) {
            if (loglevel > 0)
                fprintf(logfile, "Search PC...\n");
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
                gen_opc_pc[lj] = dc->pc;
                gen_opc_npc[lj] = dc->npc;
                gen_opc_instr_start[lj] = 1;
            }
        }
3220 3221
	last_pc = dc->pc;
	disas_sparc_insn(dc);
B
bellard 已提交
3222

3223 3224 3225 3226 3227
	if (dc->is_br)
	    break;
	/* if the next PC is different, we abort now */
	if (dc->pc != (last_pc + 4))
	    break;
B
bellard 已提交
3228 3229 3230 3231
        /* if we reach a page boundary, we stop generation so that the
           PC of a TT_TFAULT exception is always in the right page */
        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
            break;
B
bellard 已提交
3232 3233 3234
        /* if single step mode, we generate only one instruction and
           generate an exception */
        if (env->singlestep_enabled) {
B
bellard 已提交
3235
            gen_jmp_im(dc->pc);
B
bellard 已提交
3236 3237 3238 3239
            gen_op_movl_T0_0();
            gen_op_exit_tb();
            break;
        }
3240 3241
    } while ((gen_opc_ptr < gen_opc_end) &&
	     (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
B
bellard 已提交
3242 3243

 exit_gen_loop:
B
bellard 已提交
3244 3245 3246 3247
    if (!dc->is_br) {
        if (dc->pc != DYNAMIC_PC && 
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
            /* static PC and NPC: we can use direct chaining */
B
bellard 已提交
3248
            gen_branch(dc, (long)tb, dc->pc, dc->npc);
B
bellard 已提交
3249 3250
        } else {
            if (dc->pc != DYNAMIC_PC)
B
bellard 已提交
3251
                gen_jmp_im(dc->pc);
B
bellard 已提交
3252 3253 3254 3255 3256
            save_npc(dc);
            gen_op_movl_T0_0();
            gen_op_exit_tb();
        }
    }
3257
    *gen_opc_ptr = INDEX_op_end;
3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268
    if (spc) {
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
        tb->size = 0;
#if 0
        if (loglevel > 0) {
            page_dump(logfile);
        }
#endif
3269 3270
        gen_opc_jump_pc[0] = dc->jump_pc[0];
        gen_opc_jump_pc[1] = dc->jump_pc[1];
3271
    } else {
B
bellard 已提交
3272
        tb->size = last_pc + 4 - pc_start;
3273
    }
3274
#ifdef DEBUG_DISAS
B
bellard 已提交
3275
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3276
	fprintf(logfile, "--------------\n");
B
bellard 已提交
3277 3278
	fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
	target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
3279
	fprintf(logfile, "\n");
B
bellard 已提交
3280 3281 3282 3283 3284
        if (loglevel & CPU_LOG_TB_OP) {
            fprintf(logfile, "OP:\n");
            dump_ops(gen_opc_buf, gen_opparam_buf);
            fprintf(logfile, "\n");
        }
3285
    }
3286
#endif
3287
    return 0;
3288 3289
}

3290
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
3291
{
3292
    return gen_intermediate_code_internal(tb, 0, env);
3293 3294
}

3295
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
3296
{
3297
    return gen_intermediate_code_internal(tb, 1, env);
3298 3299
}

B
bellard 已提交
3300
extern int ram_size;
3301

B
bellard 已提交
3302 3303
void cpu_reset(CPUSPARCState *env)
{
3304
    memset(env, 0, sizeof(*env));
B
bellard 已提交
3305
    tlb_flush(env, 1);
3306 3307 3308
    env->cwp = 0;
    env->wim = 1;
    env->regwptr = env->regbase + (env->cwp * 16);
3309
#if defined(CONFIG_USER_ONLY)
3310
    env->user_mode_only = 1;
3311 3312 3313 3314
#ifdef TARGET_SPARC64
    env->cleanwin = NWINDOWS - 1;
    env->cansave = NWINDOWS - 1;
#endif
3315 3316
#else
    env->psrs = 1;
B
bellard 已提交
3317
    env->psrps = 1;
B
bellard 已提交
3318
    env->gregs[1] = ram_size;
B
bellard 已提交
3319
#ifdef TARGET_SPARC64
B
bellard 已提交
3320 3321
    env->pstate = PS_PRIV;
    env->pc = 0x1fff0000000ULL;
B
bellard 已提交
3322
#else
B
bellard 已提交
3323
    env->pc = 0xffd00000;
B
bellard 已提交
3324
#endif
B
bellard 已提交
3325
    env->npc = env->pc + 4;
3326
#endif
B
bellard 已提交
3327 3328 3329 3330 3331 3332
}

CPUSPARCState *cpu_sparc_init(void)
{
    CPUSPARCState *env;

B
bellard 已提交
3333 3334 3335 3336
    env = qemu_mallocz(sizeof(CPUSPARCState));
    if (!env)
	return NULL;
    cpu_exec_init(env);
B
bellard 已提交
3337
    cpu_reset(env);
3338
    return (env);
3339 3340
}

B
blueswir1 已提交
3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356
static const sparc_def_t sparc_defs[] = {
#ifdef TARGET_SPARC64
    {
        .name = "TI UltraSparc II",
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
#else
    {
        .name = "Fujitsu MB86904",
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
    },
B
blueswir1 已提交
3357 3358 3359 3360 3361 3362 3363
    {
        /* XXX: Replace with real values */
        .name = "TI SuperSparc II",
        .iu_version = 0x40000000,
        .fpu_version = 0x00000000,
        .mmu_version = 0x00000000,
    },
B
blueswir1 已提交
3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407
#endif
};

int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
{
    int ret;
    unsigned int i;

    ret = -1;
    *def = NULL;
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
            *def = &sparc_defs[i];
            ret = 0;
            break;
        }
    }

    return ret;
}

void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
{
    unsigned int i;

    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
                       sparc_defs[i].name,
                       sparc_defs[i].iu_version,
                       sparc_defs[i].fpu_version,
                       sparc_defs[i].mmu_version);
    }
}

int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
{
    env->version = def->iu_version;
    env->fsr = def->fpu_version;
#if !defined(TARGET_SPARC64)
    env->mmuregs[0] = def->mmu_version;
#endif
    return 0;
}

3408 3409
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')

B
bellard 已提交
3410 3411 3412
void cpu_dump_state(CPUState *env, FILE *f, 
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                    int flags)
3413
{
3414 3415
    int i, x;

3416
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
B
bellard 已提交
3417
    cpu_fprintf(f, "General Registers:\n");
3418
    for (i = 0; i < 4; i++)
3419
	cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
B
bellard 已提交
3420
    cpu_fprintf(f, "\n");
3421
    for (; i < 8; i++)
3422
	cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
B
bellard 已提交
3423
    cpu_fprintf(f, "\nCurrent Register Window:\n");
3424 3425
    for (x = 0; x < 3; x++) {
	for (i = 0; i < 4; i++)
3426
	    cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
3427 3428
		    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
		    env->regwptr[i + x * 8]);
B
bellard 已提交
3429
	cpu_fprintf(f, "\n");
3430
	for (; i < 8; i++)
3431
	    cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
3432 3433
		    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
		    env->regwptr[i + x * 8]);
B
bellard 已提交
3434
	cpu_fprintf(f, "\n");
3435
    }
B
bellard 已提交
3436
    cpu_fprintf(f, "\nFloating Point Registers:\n");
3437 3438
    for (i = 0; i < 32; i++) {
        if ((i & 3) == 0)
B
bellard 已提交
3439 3440
            cpu_fprintf(f, "%%f%02d:", i);
        cpu_fprintf(f, " %016lf", env->fpr[i]);
3441
        if ((i & 3) == 3)
B
bellard 已提交
3442
            cpu_fprintf(f, "\n");
3443
    }
P
pbrook 已提交
3444
#ifdef TARGET_SPARC64
3445 3446
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
		env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
P
pbrook 已提交
3447 3448 3449 3450
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
		env->cansave, env->canrestore, env->otherwin, env->wstate,
		env->cleanwin, NWINDOWS - 1 - env->cwp);
#else
B
bellard 已提交
3451
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
3452 3453
	    GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
	    GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
3454 3455
	    env->psrs?'S':'-', env->psrps?'P':'-', 
	    env->psret?'E':'-', env->wim);
P
pbrook 已提交
3456
#endif
B
bellard 已提交
3457
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
3458
}
B
bellard 已提交
3459

B
bellard 已提交
3460
#if defined(CONFIG_USER_ONLY)
3461
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
B
bellard 已提交
3462 3463 3464
{
    return addr;
}
B
bellard 已提交
3465

B
bellard 已提交
3466
#else
3467 3468
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
                                 int *access_index, target_ulong address, int rw,
B
bellard 已提交
3469 3470
                                 int is_user);

3471
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
B
bellard 已提交
3472
{
3473
    target_phys_addr_t phys_addr;
B
bellard 已提交
3474 3475 3476
    int prot, access_index;

    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
3477 3478
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
            return -1;
B
bellard 已提交
3479 3480 3481 3482
    return phys_addr;
}
#endif

B
bellard 已提交
3483 3484 3485 3486 3487
void helper_flush(target_ulong addr)
{
    addr &= ~7;
    tb_invalidate_page_range(addr, addr + 8);
}