translate.c 82.2 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 111

static GenOpFunc *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 182
};

static GenOpFunc *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 287
};

static GenOpFunc1 *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 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
// 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) \
static GenOpFunc *NAME ## _table [64] = {                                     \
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 322 323 324 325 326 327 328 329 330 331 332 333 334 335
#define GEN32(func, NAME) \
static GenOpFunc *NAME ## _table [32] = {                                     \
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 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
#ifdef TARGET_SPARC64
// 'a' versions allowed to user depending on asi
#if defined(CONFIG_USER_ONLY)
#define supervisor(dc) 0
#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 已提交
372 373 374
	case 0x82: /* Primary address space, non-faulting load */       \
	    gen_op_##width##_raw();					\
	    break;							\
B
bellard 已提交
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
	default:							\
            break;							\
	}								\
    }

#else
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
#define OP_LD_TABLE(width)						\
    static GenOpFunc *gen_op_##width[] = {				\
	&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)
#endif
#else
410 411
#if defined(CONFIG_USER_ONLY)
#define gen_op_ldst(name)        gen_op_##name##_raw()
B
bellard 已提交
412
#define OP_LD_TABLE(width)
413 414 415 416 417 418 419 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
#define supervisor(dc) 0
#else
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
#define OP_LD_TABLE(width)						      \
static GenOpFunc *gen_op_##width[] = {                                        \
    &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 已提交
451
#endif
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469

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 已提交
470 471 472 473 474 475 476 477 478
#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)
479
{
B
bellard 已提交
480
    gen_op_movl_TN_im[reg](imm);
481 482
}

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

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

B
bellard 已提交
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
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);
}

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

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

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

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

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

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

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

B
bellard 已提交
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
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
}

573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
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 已提交
599 600 601 602 603 604 605 606
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);

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

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

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);

621
    gen_goto_tb(dc, 0, pc2, pc1);
B
bellard 已提交
622 623

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

static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
{
629
    gen_goto_tb(dc, 0, pc, npc);
B
bellard 已提交
630 631 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
}

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

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

B
bellard 已提交
673 674 675
static inline void gen_mov_pc_npc(DisasContext * dc)
{
    if (dc->npc == JUMP_PC) {
B
bellard 已提交
676
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
677 678 679 680 681 682 683 684 685 686
        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 已提交
687 688
static GenOpFunc * const gen_cond[2][16] = {
    {
689
	gen_op_eval_bn,
B
bellard 已提交
690 691 692 693 694 695 696
	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,
697
	gen_op_eval_ba,
B
bellard 已提交
698 699 700 701 702 703 704 705 706 707
	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
708
	gen_op_eval_bn,
B
bellard 已提交
709 710 711 712 713 714 715
	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,
716
	gen_op_eval_ba,
B
bellard 已提交
717 718 719 720 721 722 723 724 725 726 727 728 729
	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] = {
    {
730
	gen_op_eval_bn,
B
bellard 已提交
731 732 733 734 735 736 737
	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,
738
	gen_op_eval_ba,
B
bellard 已提交
739 740 741 742 743 744 745 746 747 748
	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
    {
749
	gen_op_eval_bn,
B
bellard 已提交
750 751 752 753 754 755 756
	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,
757
	gen_op_eval_ba,
B
bellard 已提交
758 759 760 761 762 763 764 765 766
	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,
    },
    {
767
	gen_op_eval_bn,
B
bellard 已提交
768 769 770 771 772 773 774
	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,
775
	gen_op_eval_ba,
B
bellard 已提交
776 777 778 779 780 781 782 783 784
	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,
    },
    {
785
	gen_op_eval_bn,
B
bellard 已提交
786 787 788 789 790 791 792
	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,
793
	gen_op_eval_ba,
B
bellard 已提交
794 795 796 797 798 799 800 801 802 803 804 805
	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
};
806

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

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

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

879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
    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 已提交
899
        gen_fcond[cc][cond]();
900
	if (a) {
B
bellard 已提交
901
	    gen_branch_a(dc, (long)dc->tb, target, dc->npc);
902 903 904 905 906 907 908 909 910 911
            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 已提交
912 913 914
#ifdef TARGET_SPARC64
/* XXX: potentially incorrect if dynamic npc */
static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
915
{
B
bellard 已提交
916 917 918 919 920 921
    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 已提交
922
	gen_branch_a(dc, (long)dc->tb, target, dc->npc);
B
bellard 已提交
923 924 925 926 927 928 929
	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;
    }
930 931
}

B
bellard 已提交
932 933 934 935 936 937 938 939 940 941 942 943 944
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,
};
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959

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 已提交
960 961
#endif

B
bellard 已提交
962 963 964 965 966 967 968 969 970 971 972 973 974
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 已提交
975
/* before an instruction, dc->pc must be static */
976 977 978
static void disas_sparc_insn(DisasContext * dc)
{
    unsigned int insn, opc, rs1, rs2, rd;
979

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

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

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

B
bellard 已提交
1076 1077 1078 1079 1080 1081 1082
#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
1083
	    gen_op_movl_T0_im(dc->pc);
B
bellard 已提交
1084
#endif
1085
	    gen_movl_T0_reg(15);
1086
	    target += dc->pc;
B
bellard 已提交
1087
            gen_mov_pc_npc(dc);
B
bellard 已提交
1088
	    dc->npc = target;
1089 1090 1091 1092 1093 1094 1095
	}
	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 已提交
1096

1097 1098 1099
                rs1 = GET_FIELD(insn, 13, 17);
                gen_movl_reg_T0(rs1);
		if (IS_IMM) {
1100
		    rs2 = GET_FIELD(insn, 25, 31);
B
bellard 已提交
1101
#if defined(OPTIM)
1102
		    if (rs2 != 0) {
B
bellard 已提交
1103
#endif
B
bellard 已提交
1104
			gen_movl_simm_T1(rs2);
B
bellard 已提交
1105 1106
			gen_op_add_T1_T0();
#if defined(OPTIM)
1107
		    }
B
bellard 已提交
1108
#endif
1109 1110
                } else {
                    rs2 = GET_FIELD(insn, 27, 31);
B
bellard 已提交
1111 1112 1113 1114 1115 1116 1117 1118
#if defined(OPTIM)
		    if (rs2 != 0) {
#endif
			gen_movl_reg_T1(rs2);
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
#endif
1119 1120 1121
                }
                cond = GET_FIELD(insn, 3, 6);
                if (cond == 0x8) {
B
bellard 已提交
1122
                    save_state(dc);
1123
                    gen_op_trap_T0();
1124
                } else if (cond != 0) {
B
bellard 已提交
1125 1126 1127
#ifdef TARGET_SPARC64
		    /* V9 icc/xcc */
		    int cc = GET_FIELD_SP(insn, 11, 12);
B
bellard 已提交
1128 1129
		    flush_T2(dc);
                    save_state(dc);
B
bellard 已提交
1130 1131 1132 1133 1134 1135 1136
		    if (cc == 0)
			gen_cond[0][cond]();
		    else if (cc == 2)
			gen_cond[1][cond]();
		    else
			goto illegal_insn;
#else
B
bellard 已提交
1137 1138
		    flush_T2(dc);
                    save_state(dc);
B
bellard 已提交
1139 1140
		    gen_cond[0][cond]();
#endif
1141 1142
                    gen_op_trapcc_T0();
                }
B
bellard 已提交
1143 1144 1145 1146 1147
                gen_op_next_insn();
                gen_op_movl_T0_0();
                gen_op_exit_tb();
                dc->is_br = 1;
                goto jmp_insn;
1148 1149 1150 1151
            } else if (xop == 0x28) {
                rs1 = GET_FIELD(insn, 13, 17);
                switch(rs1) {
                case 0: /* rdy */
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
#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));
1163 1164
                    gen_movl_T0_reg(rd);
                    break;
B
bellard 已提交
1165
#ifdef TARGET_SPARC64
1166
		case 0x2: /* V9 rdccr */
B
bellard 已提交
1167 1168 1169
                    gen_op_rdccr();
                    gen_movl_T0_reg(rd);
                    break;
1170
		case 0x3: /* V9 rdasi */
B
bellard 已提交
1171 1172 1173
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
                    gen_movl_T0_reg(rd);
                    break;
1174
		case 0x4: /* V9 rdtick */
B
bellard 已提交
1175 1176 1177
                    gen_op_rdtick();
                    gen_movl_T0_reg(rd);
                    break;
1178
		case 0x5: /* V9 rdpc */
P
pbrook 已提交
1179 1180 1181 1182 1183
		    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 已提交
1184 1185
		    gen_movl_T0_reg(rd);
		    break;
1186
		case 0x6: /* V9 rdfprs */
B
bellard 已提交
1187 1188 1189
		    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
                    gen_movl_T0_reg(rd);
                    break;
1190 1191
                case 0xf: /* V9 membar */
                    break; /* no effect */
B
bellard 已提交
1192 1193 1194 1195 1196 1197
		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 已提交
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
		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 已提交
1216 1217
#endif
                default:
1218 1219
                    goto illegal_insn;
                }
1220
#if !defined(CONFIG_USER_ONLY)
B
bellard 已提交
1221 1222
#ifndef TARGET_SPARC64
            } else if (xop == 0x29) { /* rdpsr / V9 unimp */
1223 1224 1225 1226 1227
		if (!supervisor(dc))
		    goto priv_insn;
                gen_op_rdpsr();
                gen_movl_T0_reg(rd);
                break;
B
bellard 已提交
1228 1229
#endif
            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1230 1231
		if (!supervisor(dc))
		    goto priv_insn;
B
bellard 已提交
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 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
#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;
		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
1290 1291
                gen_movl_T0_reg(rd);
                break;
B
bellard 已提交
1292 1293 1294 1295
            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
		gen_op_flushw();
#else
1296 1297
		if (!supervisor(dc))
		    goto priv_insn;
B
bellard 已提交
1298
		gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1299
                gen_movl_T0_reg(rd);
B
bellard 已提交
1300
#endif
1301 1302
                break;
#endif
B
bellard 已提交
1303
	    } else if (xop == 0x34) {	/* FPU Operations */
B
bellard 已提交
1304 1305
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
1306
		gen_op_clear_ieee_excp_and_FTT();
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
                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 已提交
1331
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1332
			gen_op_fsqrtd();
B
bellard 已提交
1333
			gen_op_store_DT0_fpr(DFPREG(rd));
1334
			break;
B
bellard 已提交
1335 1336
		    case 0x2b: /* fsqrtq */
		        goto nfpu_insn;
1337 1338 1339 1340 1341 1342 1343
		    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 已提交
1344 1345
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1346
			gen_op_faddd();
B
bellard 已提交
1347
			gen_op_store_DT0_fpr(DFPREG(rd));
1348
			break;
B
bellard 已提交
1349 1350
		    case 0x43: /* faddq */
		        goto nfpu_insn;
1351 1352 1353 1354 1355 1356 1357
		    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 已提交
1358 1359
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1360
			gen_op_fsubd();
B
bellard 已提交
1361
			gen_op_store_DT0_fpr(DFPREG(rd));
1362
			break;
B
bellard 已提交
1363 1364
		    case 0x47: /* fsubq */
		        goto nfpu_insn;
1365 1366 1367 1368 1369 1370 1371
		    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 已提交
1372 1373
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1374 1375 1376
			gen_op_fmuld();
			gen_op_store_DT0_fpr(rd);
			break;
B
bellard 已提交
1377 1378
		    case 0x4b: /* fmulq */
		        goto nfpu_insn;
1379 1380 1381 1382 1383 1384 1385
		    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 已提交
1386 1387
                	gen_op_load_fpr_DT0(DFPREG(rs1));
			gen_op_load_fpr_DT1(DFPREG(rs2));
1388
			gen_op_fdivd();
B
bellard 已提交
1389
			gen_op_store_DT0_fpr(DFPREG(rd));
1390
			break;
B
bellard 已提交
1391 1392
		    case 0x4f: /* fdivq */
		        goto nfpu_insn;
1393 1394 1395 1396
		    case 0x69:
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fsmuld();
B
bellard 已提交
1397
			gen_op_store_DT0_fpr(DFPREG(rd));
1398
			break;
B
bellard 已提交
1399 1400
		    case 0x6e: /* fdmulq */
		        goto nfpu_insn;
1401 1402 1403 1404 1405 1406
		    case 0xc4:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fitos();
			gen_op_store_FT0_fpr(rd);
			break;
		    case 0xc6:
B
bellard 已提交
1407
                	gen_op_load_fpr_DT1(DFPREG(rs2));
1408 1409 1410
			gen_op_fdtos();
			gen_op_store_FT0_fpr(rd);
			break;
B
bellard 已提交
1411 1412
		    case 0xc7: /* fqtos */
		        goto nfpu_insn;
1413 1414 1415
		    case 0xc8:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fitod();
B
bellard 已提交
1416
			gen_op_store_DT0_fpr(DFPREG(rd));
1417 1418 1419 1420
			break;
		    case 0xc9:
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fstod();
B
bellard 已提交
1421
			gen_op_store_DT0_fpr(DFPREG(rd));
1422
			break;
B
bellard 已提交
1423 1424 1425 1426 1427 1428 1429 1430
		    case 0xcb: /* fqtod */
		        goto nfpu_insn;
		    case 0xcc: /* fitoq */
		        goto nfpu_insn;
		    case 0xcd: /* fstoq */
		        goto nfpu_insn;
		    case 0xce: /* fdtoq */
		        goto nfpu_insn;
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
		    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 已提交
1441 1442
		    case 0xd3: /* fqtoi */
		        goto nfpu_insn;
B
bellard 已提交
1443
#ifdef TARGET_SPARC64
1444
		    case 0x2: /* V9 fmovd */
B
bellard 已提交
1445 1446 1447
                	gen_op_load_fpr_DT0(DFPREG(rs2));
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1448
		    case 0x6: /* V9 fnegd */
B
bellard 已提交
1449 1450 1451 1452
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fnegd();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1453
		    case 0xa: /* V9 fabsd */
B
bellard 已提交
1454 1455 1456 1457
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fabsd();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1458
		    case 0x81: /* V9 fstox */
B
bellard 已提交
1459 1460 1461 1462
                	gen_op_load_fpr_FT1(rs2);
			gen_op_fstox();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1463
		    case 0x82: /* V9 fdtox */
B
bellard 已提交
1464 1465 1466 1467
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fdtox();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1468
		    case 0x84: /* V9 fxtos */
B
bellard 已提交
1469 1470 1471 1472
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fxtos();
			gen_op_store_FT0_fpr(rd);
			break;
1473
		    case 0x88: /* V9 fxtod */
B
bellard 已提交
1474 1475 1476 1477
                	gen_op_load_fpr_DT1(DFPREG(rs2));
			gen_op_fxtod();
			gen_op_store_DT0_fpr(DFPREG(rd));
			break;
1478 1479 1480 1481 1482
		    case 0x3: /* V9 fmovq */
		    case 0x7: /* V9 fnegq */
		    case 0xb: /* V9 fabsq */
		    case 0x83: /* V9 fqtox */
		    case 0x8c: /* V9 fxtoq */
B
bellard 已提交
1483 1484 1485
		        goto nfpu_insn;
#endif
		    default:
1486 1487
                	goto illegal_insn;
		}
B
bellard 已提交
1488
	    } else if (xop == 0x35) {	/* FPU Operations */
B
bellard 已提交
1489 1490 1491
#ifdef TARGET_SPARC64
		int cond;
#endif
B
bellard 已提交
1492 1493
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
1494
		gen_op_clear_ieee_excp_and_FTT();
1495
                rs1 = GET_FIELD(insn, 13, 17);
B
bellard 已提交
1496 1497
	        rs2 = GET_FIELD(insn, 27, 31);
	        xop = GET_FIELD(insn, 18, 26);
B
bellard 已提交
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
#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 已提交
1525
		switch (xop) {
B
bellard 已提交
1526 1527 1528 1529 1530 1531 1532 1533 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 1561 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
#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 已提交
1649 1650
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
B
bellard 已提交
1651 1652 1653
#ifdef TARGET_SPARC64
			gen_fcmps[rd & 3]();
#else
B
bellard 已提交
1654
			gen_op_fcmps();
B
bellard 已提交
1655
#endif
B
bellard 已提交
1656
			break;
B
bellard 已提交
1657 1658 1659 1660 1661 1662
		    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 已提交
1663
			gen_op_fcmpd();
B
bellard 已提交
1664
#endif
B
bellard 已提交
1665 1666 1667
			break;
		    case 0x53: /* fcmpq */
		        goto nfpu_insn;
B
bellard 已提交
1668
		    case 0x55: /* fcmpes, V9 %fcc */
B
bellard 已提交
1669 1670
                	gen_op_load_fpr_FT0(rs1);
                	gen_op_load_fpr_FT1(rs2);
B
bellard 已提交
1671
#ifdef TARGET_SPARC64
1672
			gen_fcmpes[rd & 3]();
B
bellard 已提交
1673
#else
1674
			gen_op_fcmpes();
B
bellard 已提交
1675
#endif
B
bellard 已提交
1676
			break;
B
bellard 已提交
1677 1678 1679 1680
		    case 0x56: /* fcmped, V9 %fcc */
                	gen_op_load_fpr_DT0(DFPREG(rs1));
                	gen_op_load_fpr_DT1(DFPREG(rs2));
#ifdef TARGET_SPARC64
1681
			gen_fcmped[rd & 3]();
B
bellard 已提交
1682
#else
1683
			gen_op_fcmped();
B
bellard 已提交
1684
#endif
B
bellard 已提交
1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
			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 已提交
1700
			gen_movl_simm_T1(rs2);
B
bellard 已提交
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
		    } 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 已提交
1712
			    gen_movl_simm_T1(rs2);
B
bellard 已提交
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724
			    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 已提交
1725 1726
#endif
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1727
	    } else if (xop == 0x25) { /* sll, V9 sllx */
B
bellard 已提交
1728 1729 1730 1731 1732 1733 1734 1735 1736
                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 已提交
1737 1738 1739 1740
		if (insn & (1 << 12))
		    gen_op_sllx();
		else
		    gen_op_sll();
B
bellard 已提交
1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
		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 已提交
1772
#endif
1773
            } else if (xop < 0x36) {
B
bellard 已提交
1774 1775 1776
                rs1 = GET_FIELD(insn, 13, 17);
		gen_movl_reg_T0(rs1);
		if (IS_IMM) {	/* immediate */
1777
                    rs2 = GET_FIELDs(insn, 19, 31);
B
bellard 已提交
1778
                    gen_movl_simm_T1(rs2);
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796
                } 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 已提交
1797 1798 1799 1800
			gen_op_or_T1_T0();
			if (xop & 0x10)
			    gen_op_logic_T0_cc();
			break;
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
                    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)
1829 1830 1831
                            gen_op_addx_T1_T0_cc();
                        else
                            gen_op_addx_T1_T0();
1832
                        break;
P
pbrook 已提交
1833 1834 1835 1836 1837
#ifdef TARGET_SPARC64
		    case 0x9: /* V9 mulx */
                        gen_op_mulx_T1_T0();
                        break;
#endif
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
                    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)
1850 1851 1852
                            gen_op_subx_T1_T0_cc();
                        else
                            gen_op_subx_T1_T0();
1853
                        break;
P
pbrook 已提交
1854 1855 1856 1857 1858
#ifdef TARGET_SPARC64
		    case 0xd: /* V9 udivx */
                        gen_op_udivx_T1_T0();
                        break;
#endif
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
                    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 已提交
1872
		    gen_movl_T0_reg(rd);
1873 1874
                } else {
                    switch (xop) {
B
bellard 已提交
1875
		    case 0x20: /* taddcc */
1876 1877 1878
			gen_op_tadd_T1_T0_cc();
		        gen_movl_T0_reg(rd);
			break;
B
bellard 已提交
1879
		    case 0x21: /* tsubcc */
1880 1881 1882
			gen_op_tsub_T1_T0_cc();
		        gen_movl_T0_reg(rd);
			break;
B
bellard 已提交
1883
		    case 0x22: /* taddcctv */
1884 1885 1886
			gen_op_tadd_T1_T0_ccTV();
		        gen_movl_T0_reg(rd);
			break;
B
bellard 已提交
1887
		    case 0x23: /* tsubcctv */
1888 1889 1890
			gen_op_tsub_T1_T0_ccTV();
		        gen_movl_T0_reg(rd);
			break;
1891 1892 1893 1894
                    case 0x24: /* mulscc */
                        gen_op_mulscc_T1_T0();
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1895 1896
#ifndef TARGET_SPARC64
                    case 0x25:	/* sll */
B
bellard 已提交
1897
			gen_op_sll();
1898 1899
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1900
                    case 0x26:  /* srl */
B
bellard 已提交
1901
			gen_op_srl();
1902 1903
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1904
                    case 0x27:  /* sra */
B
bellard 已提交
1905
			gen_op_sra();
1906 1907
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
1908
#endif
1909 1910 1911
                    case 0x30:
                        {
                            switch(rd) {
B
bellard 已提交
1912 1913 1914
                            case 0: /* wry */
				gen_op_xor_T1_T0();
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1915
                                break;
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926
#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
1927
			    case 0x2: /* V9 wrccr */
B
bellard 已提交
1928 1929
                                gen_op_wrccr();
				break;
1930
			    case 0x3: /* V9 wrasi */
B
bellard 已提交
1931 1932
				gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
				break;
1933
			    case 0x6: /* V9 wrfprs */
1934
				gen_op_xor_T1_T0();
B
bellard 已提交
1935
				gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
1936 1937 1938 1939 1940
                                save_state(dc);
                                gen_op_next_insn();
                                gen_op_movl_T0_0();
                                gen_op_exit_tb();
                                dc->is_br = 1;
B
bellard 已提交
1941 1942 1943 1944 1945 1946 1947
				break;
			    case 0xf: /* V9 sir, nop if user */
#if !defined(CONFIG_USER_ONLY)
				if (supervisor(dc))
				    gen_op_sir();
#endif
				break;
B
bellard 已提交
1948 1949 1950 1951 1952
			    case 0x13: /* Graphics Status */
                                if (gen_trap_ifnofpu(dc))
                                    goto jmp_insn;
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
				break;
B
bellard 已提交
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
			    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 已提交
1971
#endif
B
bellard 已提交
1972 1973 1974
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
				break;

B
bellard 已提交
1975 1976 1977 1978 1979 1980
			    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 已提交
1981
#endif
B
bellard 已提交
1982
                            default:
1983 1984 1985 1986
                                goto illegal_insn;
                            }
                        }
                        break;
1987
#if !defined(CONFIG_USER_ONLY)
1988
                    case 0x31: /* wrpsr, V9 saved, restored */
1989 1990 1991
                        {
			    if (!supervisor(dc))
				goto priv_insn;
B
bellard 已提交
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
#ifdef TARGET_SPARC64
			    switch (rd) {
			    case 0:
				gen_op_saved();
				break;
			    case 1:
				gen_op_restored();
				break;
			    default:
                                goto illegal_insn;
                            }
#else
2004 2005
                            gen_op_xor_T1_T0();
                            gen_op_wrpsr();
B
bellard 已提交
2006 2007 2008 2009 2010
                            save_state(dc);
                            gen_op_next_insn();
			    gen_op_movl_T0_0();
			    gen_op_exit_tb();
			    dc->is_br = 1;
B
bellard 已提交
2011
#endif
2012 2013
                        }
                        break;
2014
                    case 0x32: /* wrwim, V9 wrpr */
2015 2016 2017 2018
                        {
			    if (!supervisor(dc))
				goto priv_insn;
                            gen_op_xor_T1_T0();
B
bellard 已提交
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
#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 已提交
2037
				gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
B
bellard 已提交
2038 2039 2040
				break;
			    case 6: // pstate
				gen_op_wrpstate();
P
pbrook 已提交
2041 2042 2043 2044 2045
                                save_state(dc);
                                gen_op_next_insn();
                                gen_op_movl_T0_0();
                                gen_op_exit_tb();
                                dc->is_br = 1;
B
bellard 已提交
2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074
				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;
			    default:
				goto illegal_insn;
			    }
#else
B
bellard 已提交
2075
			    gen_op_wrwim();
B
bellard 已提交
2076
#endif
2077 2078
                        }
                        break;
B
bellard 已提交
2079 2080
#ifndef TARGET_SPARC64
                    case 0x33: /* wrtbr, V9 unimp */
2081 2082 2083 2084
                        {
			    if (!supervisor(dc))
				goto priv_insn;
                            gen_op_xor_T1_T0();
B
bellard 已提交
2085
			    gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
2086 2087 2088
                        }
                        break;
#endif
B
bellard 已提交
2089 2090
#endif
#ifdef TARGET_SPARC64
2091
		    case 0x2c: /* V9 movcc */
B
bellard 已提交
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
			{
			    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;
			}
2119
		    case 0x2d: /* V9 sdivx */
B
bellard 已提交
2120 2121 2122
                        gen_op_sdivx_T1_T0();
			gen_movl_T0_reg(rd);
                        break;
2123
		    case 0x2e: /* V9 popc */
B
bellard 已提交
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136
			{
			    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);
			}
2137
		    case 0x2f: /* V9 movr */
B
bellard 已提交
2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
			{
			    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 已提交
2159 2160 2161
			goto illegal_insn;
		    }
		}
2162 2163 2164 2165 2166 2167 2168 2169 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 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 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);

                switch (opf) {
                case 0x018: /* VIS I alignaddr */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_alignaddr();
                    gen_movl_T0_reg(rd);
                    break;
                case 0x01a: /* VIS I alignaddrl */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    // XXX
                    break;
                case 0x048: /* VIS I faligndata */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_load_fpr_DT1(rs2);
                    gen_op_faligndata();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x060: /* VIS I fzero */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_movl_DT0_0();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x061: /* VIS I fzeros */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_movl_FT0_0();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x074: /* VIS I fsrc1 */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_load_fpr_DT0(rs1);
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x075: /* VIS I fsrc1s */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x078: /* VIS I fsrc2 */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_load_fpr_DT0(rs2);
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x079: /* VIS I fsrc2s */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x07e: /* VIS I fone */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_movl_DT0_1();
                    gen_op_store_DT0_fpr(rd);
                    break;
                case 0x07f: /* VIS I fones */
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    gen_op_movl_FT0_1();
                    gen_op_store_FT0_fpr(rd);
                    break;
                default:
                    goto illegal_insn;
                }
#else
	        goto ncp_insn;
#endif
            } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
2245 2246 2247 2248 2249
#ifdef TARGET_SPARC64
	        goto illegal_insn;
#else
	        goto ncp_insn;
#endif
B
bellard 已提交
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
#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 已提交
2275
		gen_op_restore();
B
bellard 已提交
2276 2277 2278 2279 2280
		gen_mov_pc_npc(dc);
		gen_op_movl_npc_T0();
		dc->npc = DYNAMIC_PC;
		goto jmp_insn;
#endif
B
bellard 已提交
2281 2282 2283 2284 2285 2286 2287
	    } 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) {
2288
#endif
B
bellard 已提交
2289
			gen_movl_simm_T1(rs2);
B
bellard 已提交
2290 2291 2292
			gen_op_add_T1_T0();
#if defined(OPTIM)
		    }
2293
#endif
B
bellard 已提交
2294 2295 2296 2297 2298 2299 2300 2301 2302
                } 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)
		    }
2303
#endif
2304
                }
B
bellard 已提交
2305 2306 2307 2308
		switch (xop) {
		case 0x38:	/* jmpl */
		    {
			if (rd != 0) {
P
pbrook 已提交
2309 2310 2311 2312 2313 2314 2315
#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 已提交
2316
			    gen_op_movl_T1_im(dc->pc);
P
pbrook 已提交
2317
#endif
B
bellard 已提交
2318
			    gen_movl_T1_reg(rd);
B
bellard 已提交
2319
			}
B
bellard 已提交
2320 2321
                        gen_mov_pc_npc(dc);
			gen_op_movl_npc_T0();
B
bellard 已提交
2322 2323 2324
			dc->npc = DYNAMIC_PC;
		    }
		    goto jmp_insn;
B
bellard 已提交
2325
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2326
		case 0x39:	/* rett, V9 return */
B
bellard 已提交
2327 2328 2329
		    {
			if (!supervisor(dc))
			    goto priv_insn;
B
bellard 已提交
2330
                        gen_mov_pc_npc(dc);
B
bellard 已提交
2331
			gen_op_movl_npc_T0();
B
bellard 已提交
2332
			dc->npc = DYNAMIC_PC;
B
bellard 已提交
2333 2334
			gen_op_rett();
		    }
B
bellard 已提交
2335
		    goto jmp_insn;
B
bellard 已提交
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349
#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 已提交
2350
#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
2351
		case 0x3e:      /* V9 done/retry */
B
bellard 已提交
2352 2353 2354 2355 2356
		    {
			switch (rd) {
			case 0:
			    if (!supervisor(dc))
				goto priv_insn;
B
bellard 已提交
2357 2358
			    dc->npc = DYNAMIC_PC;
			    dc->pc = DYNAMIC_PC;
B
bellard 已提交
2359
			    gen_op_done();
B
bellard 已提交
2360
			    goto jmp_insn;
B
bellard 已提交
2361 2362 2363
			case 1:
			    if (!supervisor(dc))
				goto priv_insn;
B
bellard 已提交
2364 2365
			    dc->npc = DYNAMIC_PC;
			    dc->pc = DYNAMIC_PC;
B
bellard 已提交
2366
			    gen_op_retry();
B
bellard 已提交
2367
			    goto jmp_insn;
B
bellard 已提交
2368 2369 2370 2371 2372 2373 2374
			default:
			    goto illegal_insn;
			}
		    }
		    break;
#endif
		default:
B
bellard 已提交
2375 2376
		    goto illegal_insn;
		}
2377 2378 2379
            }
	    break;
	}
2380
	break;
2381 2382 2383 2384 2385 2386 2387
    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 已提交
2388
#if defined(OPTIM)
2389
		if (rs2 != 0) {
B
bellard 已提交
2390
#endif
B
bellard 已提交
2391
		    gen_movl_simm_T1(rs2);
2392
		    gen_op_add_T1_T0();
B
bellard 已提交
2393
#if defined(OPTIM)
2394
		}
B
bellard 已提交
2395
#endif
2396 2397
	    } else {		/* register */
		rs2 = GET_FIELD(insn, 27, 31);
B
bellard 已提交
2398 2399 2400 2401 2402 2403 2404 2405
#if defined(OPTIM)
		if (rs2 != 0) {
#endif
		    gen_movl_reg_T1(rs2);
		    gen_op_add_T1_T0();
#if defined(OPTIM)
		}
#endif
2406
	    }
B
bellard 已提交
2407
	    if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
B
blueswir1 已提交
2408 2409
		    (xop > 0x17 && xop <= 0x1d ) || \
		    (xop > 0x2c && xop <= 0x33) || xop == 0x1f) {
2410 2411
		switch (xop) {
		case 0x0:	/* load word */
2412
		    gen_op_ldst(ld);
2413 2414
		    break;
		case 0x1:	/* load unsigned byte */
2415
		    gen_op_ldst(ldub);
2416 2417
		    break;
		case 0x2:	/* load unsigned halfword */
2418
		    gen_op_ldst(lduh);
2419 2420
		    break;
		case 0x3:	/* load double word */
2421 2422
		    if (rd & 1)
                        goto illegal_insn;
2423
		    gen_op_ldst(ldd);
2424 2425 2426
		    gen_movl_T0_reg(rd + 1);
		    break;
		case 0x9:	/* load signed byte */
2427
		    gen_op_ldst(ldsb);
2428 2429
		    break;
		case 0xa:	/* load signed halfword */
2430
		    gen_op_ldst(ldsh);
2431 2432
		    break;
		case 0xd:	/* ldstub -- XXX: should be atomically */
2433
		    gen_op_ldst(ldstub);
2434 2435
		    break;
		case 0x0f:	/* swap register with memory. Also atomically */
B
bellard 已提交
2436
		    gen_movl_reg_T1(rd);
2437 2438
		    gen_op_ldst(swap);
		    break;
B
bellard 已提交
2439
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2440
		case 0x10:	/* load word alternate */
B
bellard 已提交
2441
#ifndef TARGET_SPARC64
2442 2443
		    if (IS_IMM)
			goto illegal_insn;
2444 2445
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2446
#endif
2447 2448 2449
		    gen_op_lda(insn, 1, 4, 0);
		    break;
		case 0x11:	/* load unsigned byte alternate */
B
bellard 已提交
2450
#ifndef TARGET_SPARC64
2451 2452
		    if (IS_IMM)
			goto illegal_insn;
2453 2454
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2455
#endif
2456 2457 2458
		    gen_op_lduba(insn, 1, 1, 0);
		    break;
		case 0x12:	/* load unsigned halfword alternate */
B
bellard 已提交
2459
#ifndef TARGET_SPARC64
2460 2461
		    if (IS_IMM)
			goto illegal_insn;
2462 2463
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2464
#endif
2465 2466 2467
		    gen_op_lduha(insn, 1, 2, 0);
		    break;
		case 0x13:	/* load double word alternate */
B
bellard 已提交
2468
#ifndef TARGET_SPARC64
2469 2470
		    if (IS_IMM)
			goto illegal_insn;
2471 2472
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2473
#endif
2474 2475
		    if (rd & 1)
                        goto illegal_insn;
2476 2477 2478 2479
		    gen_op_ldda(insn, 1, 8, 0);
		    gen_movl_T0_reg(rd + 1);
		    break;
		case 0x19:	/* load signed byte alternate */
B
bellard 已提交
2480
#ifndef TARGET_SPARC64
2481 2482
		    if (IS_IMM)
			goto illegal_insn;
2483 2484
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2485
#endif
2486 2487 2488
		    gen_op_ldsba(insn, 1, 1, 1);
		    break;
		case 0x1a:	/* load signed halfword alternate */
B
bellard 已提交
2489
#ifndef TARGET_SPARC64
2490 2491
		    if (IS_IMM)
			goto illegal_insn;
2492 2493
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2494
#endif
2495 2496 2497
		    gen_op_ldsha(insn, 1, 2 ,1);
		    break;
		case 0x1d:	/* ldstuba -- XXX: should be atomically */
B
bellard 已提交
2498
#ifndef TARGET_SPARC64
2499 2500
		    if (IS_IMM)
			goto illegal_insn;
2501 2502
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2503
#endif
2504 2505 2506
		    gen_op_ldstuba(insn, 1, 1, 0);
		    break;
		case 0x1f:	/* swap reg with alt. memory. Also atomically */
B
bellard 已提交
2507
#ifndef TARGET_SPARC64
2508 2509
		    if (IS_IMM)
			goto illegal_insn;
2510 2511
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2512
#endif
B
bellard 已提交
2513
		    gen_movl_reg_T1(rd);
2514
		    gen_op_swapa(insn, 1, 4, 0);
2515
		    break;
B
bellard 已提交
2516 2517

#ifndef TARGET_SPARC64
2518 2519 2520 2521
		case 0x30: /* ldc */
		case 0x31: /* ldcsr */
		case 0x33: /* lddc */
		    goto ncp_insn;
B
bellard 已提交
2522 2523 2524 2525 2526
                    /* avoid warnings */
                    (void) &gen_op_stfa;
                    (void) &gen_op_stdfa;
                    (void) &gen_op_ldfa;
                    (void) &gen_op_lddfa;
B
bellard 已提交
2527 2528 2529 2530
#else
#if !defined(CONFIG_USER_ONLY)
		    (void) &gen_op_cas;
		    (void) &gen_op_casx;
B
bellard 已提交
2531
#endif
B
bellard 已提交
2532 2533 2534
#endif
#endif
#ifdef TARGET_SPARC64
2535
		case 0x08: /* V9 ldsw */
B
bellard 已提交
2536 2537
		    gen_op_ldst(ldsw);
		    break;
2538
		case 0x0b: /* V9 ldx */
B
bellard 已提交
2539 2540
		    gen_op_ldst(ldx);
		    break;
2541
		case 0x18: /* V9 ldswa */
B
bellard 已提交
2542 2543
		    gen_op_ldswa(insn, 1, 4, 1);
		    break;
2544
		case 0x1b: /* V9 ldxa */
B
bellard 已提交
2545 2546 2547 2548
		    gen_op_ldxa(insn, 1, 8, 0);
		    break;
		case 0x2d: /* V9 prefetch, no effect */
		    goto skip_move;
2549
		case 0x30: /* V9 ldfa */
B
bellard 已提交
2550 2551
		    gen_op_ldfa(insn, 1, 8, 0); // XXX
		    break;
2552
		case 0x33: /* V9 lddfa */
B
bellard 已提交
2553
		    gen_op_lddfa(insn, 1, 8, 0); // XXX
2554

B
bellard 已提交
2555 2556 2557
		    break;
		case 0x3d: /* V9 prefetcha, no effect */
		    goto skip_move;
2558
		case 0x32: /* V9 ldqfa */
B
bellard 已提交
2559 2560 2561
		    goto nfpu_insn;
#endif
		default:
B
bellard 已提交
2562
		    goto illegal_insn;
2563
		}
2564
		gen_movl_T1_reg(rd);
B
bellard 已提交
2565 2566 2567
#ifdef TARGET_SPARC64
	    skip_move: ;
#endif
2568
	    } else if (xop >= 0x20 && xop < 0x24) {
B
bellard 已提交
2569 2570
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
2571 2572 2573 2574 2575 2576
		switch (xop) {
		case 0x20:	/* load fpreg */
		    gen_op_ldst(ldf);
		    gen_op_store_FT0_fpr(rd);
		    break;
		case 0x21:	/* load fsr */
B
bellard 已提交
2577
		    gen_op_ldst(ldf);
2578 2579
		    gen_op_ldfsr();
		    break;
2580 2581
		case 0x22:      /* load quad fpreg */
		    goto nfpu_insn;
2582 2583
		case 0x23:	/* load double fpreg */
		    gen_op_ldst(lddf);
B
bellard 已提交
2584
		    gen_op_store_DT0_fpr(DFPREG(rd));
2585
		    break;
B
bellard 已提交
2586 2587
		default:
		    goto illegal_insn;
2588
		}
B
bellard 已提交
2589 2590
	    } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
		       xop == 0xe || xop == 0x1e) {
2591 2592 2593
		gen_movl_reg_T1(rd);
		switch (xop) {
		case 0x4:
2594
		    gen_op_ldst(st);
2595 2596
		    break;
		case 0x5:
2597
		    gen_op_ldst(stb);
2598 2599
		    break;
		case 0x6:
2600
		    gen_op_ldst(sth);
2601 2602
		    break;
		case 0x7:
2603 2604
		    if (rd & 1)
                        goto illegal_insn;
B
bellard 已提交
2605
                    flush_T2(dc);
2606
		    gen_movl_reg_T2(rd + 1);
2607 2608
		    gen_op_ldst(std);
		    break;
B
bellard 已提交
2609
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2610
		case 0x14:
B
bellard 已提交
2611
#ifndef TARGET_SPARC64
2612 2613
		    if (IS_IMM)
			goto illegal_insn;
2614 2615
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2616
#endif
2617
		    gen_op_sta(insn, 0, 4, 0);
B
bellard 已提交
2618
                    break;
2619
		case 0x15:
B
bellard 已提交
2620
#ifndef TARGET_SPARC64
2621 2622
		    if (IS_IMM)
			goto illegal_insn;
2623 2624
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2625
#endif
2626
		    gen_op_stba(insn, 0, 1, 0);
B
bellard 已提交
2627
                    break;
2628
		case 0x16:
B
bellard 已提交
2629
#ifndef TARGET_SPARC64
2630 2631
		    if (IS_IMM)
			goto illegal_insn;
2632 2633
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2634
#endif
2635
		    gen_op_stha(insn, 0, 2, 0);
B
bellard 已提交
2636
                    break;
2637
		case 0x17:
B
bellard 已提交
2638
#ifndef TARGET_SPARC64
2639 2640
		    if (IS_IMM)
			goto illegal_insn;
2641 2642
		    if (!supervisor(dc))
			goto priv_insn;
B
bellard 已提交
2643
#endif
2644 2645
		    if (rd & 1)
                        goto illegal_insn;
2646 2647 2648
                    flush_T2(dc);
		    gen_movl_reg_T2(rd + 1);
		    gen_op_stda(insn, 0, 8, 0);
B
bellard 已提交
2649
                    break;
B
bellard 已提交
2650
#endif
B
bellard 已提交
2651
#ifdef TARGET_SPARC64
2652
		case 0x0e: /* V9 stx */
B
bellard 已提交
2653 2654
		    gen_op_ldst(stx);
		    break;
2655
		case 0x1e: /* V9 stxa */
B
bellard 已提交
2656 2657 2658 2659
		    gen_op_stxa(insn, 0, 8, 0); // XXX
		    break;
#endif
		default:
B
bellard 已提交
2660
		    goto illegal_insn;
2661
		}
2662
	    } else if (xop > 0x23 && xop < 0x28) {
B
bellard 已提交
2663 2664
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
2665 2666 2667 2668 2669
		switch (xop) {
		case 0x24:
                    gen_op_load_fpr_FT0(rd);
		    gen_op_ldst(stf);
		    break;
2670
		case 0x25: /* stfsr, V9 stxfsr */
2671
		    gen_op_stfsr();
B
bellard 已提交
2672
		    gen_op_ldst(stf);
2673
		    break;
B
blueswir1 已提交
2674
#if !defined(CONFIG_USER_ONLY)
2675
		case 0x26: /* stdfq */
B
blueswir1 已提交
2676 2677 2678 2679 2680 2681
		    if (!supervisor(dc))
			goto priv_insn;
		    if (gen_trap_ifnofpu(dc))
			goto jmp_insn;
		    goto nfq_insn;
#endif
2682
		case 0x27:
B
bellard 已提交
2683
                    gen_op_load_fpr_DT0(DFPREG(rd));
2684 2685
		    gen_op_ldst(stdf);
		    break;
B
bellard 已提交
2686
		default:
B
bellard 已提交
2687 2688 2689 2690
		    goto illegal_insn;
		}
	    } else if (xop > 0x33 && xop < 0x3f) {
		switch (xop) {
2691
#ifdef TARGET_SPARC64
2692
		case 0x34: /* V9 stfa */
B
bellard 已提交
2693 2694
		    gen_op_stfa(insn, 0, 0, 0); // XXX
		    break;
2695
		case 0x37: /* V9 stdfa */
B
bellard 已提交
2696 2697
		    gen_op_stdfa(insn, 0, 0, 0); // XXX
		    break;
2698
		case 0x3c: /* V9 casa */
B
bellard 已提交
2699 2700
		    gen_op_casa(insn, 0, 4, 0); // XXX
		    break;
2701
		case 0x3e: /* V9 casxa */
B
bellard 已提交
2702 2703
		    gen_op_casxa(insn, 0, 8, 0); // XXX
		    break;
2704
		case 0x36: /* V9 stqfa */
B
bellard 已提交
2705
		    goto nfpu_insn;
2706 2707 2708 2709 2710 2711 2712
#else
		case 0x34: /* stc */
		case 0x35: /* stcsr */
		case 0x36: /* stdcq */
		case 0x37: /* stdc */
		    goto ncp_insn;
#endif
B
bellard 已提交
2713
		default:
B
bellard 已提交
2714
		    goto illegal_insn;
2715 2716
		}
            }
B
bellard 已提交
2717 2718
	    else
		goto illegal_insn;
2719
	}
2720
	break;
2721 2722
    }
    /* default case for non jump instructions */
B
bellard 已提交
2723 2724 2725 2726 2727
    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 已提交
2728
        gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
2729 2730
        dc->is_br = 1;
    } else {
2731 2732 2733
	dc->pc = dc->npc;
	dc->npc = dc->npc + 4;
    }
B
bellard 已提交
2734
 jmp_insn:
2735 2736
    return;
 illegal_insn:
B
bellard 已提交
2737
    save_state(dc);
2738 2739
    gen_op_exception(TT_ILL_INSN);
    dc->is_br = 1;
2740
    return;
B
bellard 已提交
2741
#if !defined(CONFIG_USER_ONLY)
2742 2743 2744 2745
 priv_insn:
    save_state(dc);
    gen_op_exception(TT_PRIV_INSN);
    dc->is_br = 1;
B
bellard 已提交
2746 2747 2748 2749 2750 2751
    return;
#endif
 nfpu_insn:
    save_state(dc);
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
    dc->is_br = 1;
2752
    return;
B
blueswir1 已提交
2753 2754 2755 2756 2757 2758 2759
#if !defined(CONFIG_USER_ONLY)
 nfq_insn:
    save_state(dc);
    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
    dc->is_br = 1;
    return;
#endif
2760 2761 2762 2763 2764 2765 2766
#ifndef TARGET_SPARC64
 ncp_insn:
    save_state(dc);
    gen_op_exception(TT_NCP_INSN);
    dc->is_br = 1;
    return;
#endif
2767 2768
}

2769
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2770
						 int spc, CPUSPARCState *env)
2771
{
B
bellard 已提交
2772
    target_ulong pc_start, last_pc;
2773 2774
    uint16_t *gen_opc_end;
    DisasContext dc1, *dc = &dc1;
2775
    int j, lj = -1;
2776 2777 2778

    memset(dc, 0, sizeof(DisasContext));
    dc->tb = tb;
B
bellard 已提交
2779
    pc_start = tb->pc;
2780
    dc->pc = pc_start;
B
bellard 已提交
2781
    last_pc = dc->pc;
B
bellard 已提交
2782
    dc->npc = (target_ulong) tb->cs_base;
2783 2784
#if defined(CONFIG_USER_ONLY)
    dc->mem_idx = 0;
B
bellard 已提交
2785
    dc->fpu_enabled = 1;
2786 2787
#else
    dc->mem_idx = ((env->psrs) != 0);
B
bellard 已提交
2788 2789 2790 2791 2792
#ifdef TARGET_SPARC64
    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
#else
    dc->fpu_enabled = ((env->psref) != 0);
#endif
2793
#endif
2794 2795 2796
    gen_opc_ptr = gen_opc_buf;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
    gen_opparam_ptr = gen_opparam_buf;
B
bellard 已提交
2797
    nb_gen_labels = 0;
2798 2799

    do {
2800 2801 2802
        if (env->nb_breakpoints > 0) {
            for(j = 0; j < env->nb_breakpoints; j++) {
                if (env->breakpoints[j] == dc->pc) {
B
bellard 已提交
2803 2804 2805 2806 2807 2808 2809
		    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;
2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825
                }
            }
        }
        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;
            }
        }
2826 2827
	last_pc = dc->pc;
	disas_sparc_insn(dc);
B
bellard 已提交
2828

2829 2830 2831 2832 2833
	if (dc->is_br)
	    break;
	/* if the next PC is different, we abort now */
	if (dc->pc != (last_pc + 4))
	    break;
B
bellard 已提交
2834 2835 2836 2837
        /* 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 已提交
2838 2839 2840
        /* if single step mode, we generate only one instruction and
           generate an exception */
        if (env->singlestep_enabled) {
B
bellard 已提交
2841
            gen_jmp_im(dc->pc);
B
bellard 已提交
2842 2843 2844 2845
            gen_op_movl_T0_0();
            gen_op_exit_tb();
            break;
        }
2846 2847
    } while ((gen_opc_ptr < gen_opc_end) &&
	     (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
B
bellard 已提交
2848 2849

 exit_gen_loop:
B
bellard 已提交
2850 2851 2852 2853
    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 已提交
2854
            gen_branch(dc, (long)tb, dc->pc, dc->npc);
B
bellard 已提交
2855 2856
        } else {
            if (dc->pc != DYNAMIC_PC)
B
bellard 已提交
2857
                gen_jmp_im(dc->pc);
B
bellard 已提交
2858 2859 2860 2861 2862
            save_npc(dc);
            gen_op_movl_T0_0();
            gen_op_exit_tb();
        }
    }
2863
    *gen_opc_ptr = INDEX_op_end;
2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874
    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
2875 2876
        gen_opc_jump_pc[0] = dc->jump_pc[0];
        gen_opc_jump_pc[1] = dc->jump_pc[1];
2877
    } else {
B
bellard 已提交
2878
        tb->size = last_pc + 4 - pc_start;
2879
    }
2880
#ifdef DEBUG_DISAS
B
bellard 已提交
2881
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2882
	fprintf(logfile, "--------------\n");
B
bellard 已提交
2883 2884
	fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
	target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2885
	fprintf(logfile, "\n");
B
bellard 已提交
2886 2887 2888 2889 2890
        if (loglevel & CPU_LOG_TB_OP) {
            fprintf(logfile, "OP:\n");
            dump_ops(gen_opc_buf, gen_opparam_buf);
            fprintf(logfile, "\n");
        }
2891
    }
2892
#endif
2893
    return 0;
2894 2895
}

2896
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2897
{
2898
    return gen_intermediate_code_internal(tb, 0, env);
2899 2900
}

2901
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2902
{
2903
    return gen_intermediate_code_internal(tb, 1, env);
2904 2905
}

B
bellard 已提交
2906
extern int ram_size;
2907

B
bellard 已提交
2908 2909
void cpu_reset(CPUSPARCState *env)
{
2910
    memset(env, 0, sizeof(*env));
B
bellard 已提交
2911
    tlb_flush(env, 1);
2912 2913 2914
    env->cwp = 0;
    env->wim = 1;
    env->regwptr = env->regbase + (env->cwp * 16);
2915
#if defined(CONFIG_USER_ONLY)
2916
    env->user_mode_only = 1;
2917 2918 2919 2920
#ifdef TARGET_SPARC64
    env->cleanwin = NWINDOWS - 1;
    env->cansave = NWINDOWS - 1;
#endif
2921 2922
#else
    env->psrs = 1;
B
bellard 已提交
2923
    env->psrps = 1;
B
bellard 已提交
2924
    env->gregs[1] = ram_size;
B
bellard 已提交
2925
#ifdef TARGET_SPARC64
B
bellard 已提交
2926 2927
    env->pstate = PS_PRIV;
    env->pc = 0x1fff0000000ULL;
B
bellard 已提交
2928
#else
B
bellard 已提交
2929
    env->pc = 0xffd00000;
B
bellard 已提交
2930
#endif
B
bellard 已提交
2931
    env->npc = env->pc + 4;
2932
#endif
B
bellard 已提交
2933 2934 2935 2936 2937 2938
}

CPUSPARCState *cpu_sparc_init(void)
{
    CPUSPARCState *env;

B
bellard 已提交
2939 2940 2941 2942
    env = qemu_mallocz(sizeof(CPUSPARCState));
    if (!env)
	return NULL;
    cpu_exec_init(env);
B
bellard 已提交
2943
    cpu_reset(env);
2944
    return (env);
2945 2946
}

B
blueswir1 已提交
2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962
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 已提交
2963 2964 2965 2966 2967 2968 2969
    {
        /* XXX: Replace with real values */
        .name = "TI SuperSparc II",
        .iu_version = 0x40000000,
        .fpu_version = 0x00000000,
        .mmu_version = 0x00000000,
    },
B
blueswir1 已提交
2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013
#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;
}

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

B
bellard 已提交
3016 3017 3018
void cpu_dump_state(CPUState *env, FILE *f, 
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                    int flags)
3019
{
3020 3021
    int i, x;

3022
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
B
bellard 已提交
3023
    cpu_fprintf(f, "General Registers:\n");
3024
    for (i = 0; i < 4; i++)
3025
	cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
B
bellard 已提交
3026
    cpu_fprintf(f, "\n");
3027
    for (; i < 8; i++)
3028
	cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
B
bellard 已提交
3029
    cpu_fprintf(f, "\nCurrent Register Window:\n");
3030 3031
    for (x = 0; x < 3; x++) {
	for (i = 0; i < 4; i++)
3032
	    cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
3033 3034
		    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
		    env->regwptr[i + x * 8]);
B
bellard 已提交
3035
	cpu_fprintf(f, "\n");
3036
	for (; i < 8; i++)
3037
	    cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
3038 3039
		    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
		    env->regwptr[i + x * 8]);
B
bellard 已提交
3040
	cpu_fprintf(f, "\n");
3041
    }
B
bellard 已提交
3042
    cpu_fprintf(f, "\nFloating Point Registers:\n");
3043 3044
    for (i = 0; i < 32; i++) {
        if ((i & 3) == 0)
B
bellard 已提交
3045 3046
            cpu_fprintf(f, "%%f%02d:", i);
        cpu_fprintf(f, " %016lf", env->fpr[i]);
3047
        if ((i & 3) == 3)
B
bellard 已提交
3048
            cpu_fprintf(f, "\n");
3049
    }
P
pbrook 已提交
3050
#ifdef TARGET_SPARC64
3051 3052
    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 已提交
3053 3054 3055 3056
    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 已提交
3057
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
3058 3059
	    GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
	    GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
3060 3061
	    env->psrs?'S':'-', env->psrps?'P':'-', 
	    env->psret?'E':'-', env->wim);
P
pbrook 已提交
3062
#endif
B
bellard 已提交
3063
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
3064
}
B
bellard 已提交
3065

B
bellard 已提交
3066
#if defined(CONFIG_USER_ONLY)
3067
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
B
bellard 已提交
3068 3069 3070
{
    return addr;
}
B
bellard 已提交
3071

B
bellard 已提交
3072
#else
3073 3074
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
                                 int *access_index, target_ulong address, int rw,
B
bellard 已提交
3075 3076
                                 int is_user);

3077
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
B
bellard 已提交
3078
{
3079
    target_phys_addr_t phys_addr;
B
bellard 已提交
3080 3081 3082
    int prot, access_index;

    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
3083 3084
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
            return -1;
B
bellard 已提交
3085 3086 3087 3088
    return phys_addr;
}
#endif

B
bellard 已提交
3089 3090 3091 3092 3093
void helper_flush(target_ulong addr)
{
    addr &= ~7;
    tb_invalidate_page_range(addr, addr + 8);
}