translate.c 162.7 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
*/
29 30 31 32 33 34 35 36 37 38

#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"
B
blueswir1 已提交
39
#include "helper.h"
B
bellard 已提交
40
#include "tcg-op.h"
41 42 43

#define DEBUG_DISAS

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

B
blueswir1 已提交
48 49 50 51 52
/* global register indexes */
static TCGv cpu_env, cpu_T[3], cpu_regwptr;
/* local register indexes (only used inside old micro ops) */
static TCGv cpu_tmp0;

53
typedef struct DisasContext {
B
blueswir1 已提交
54 55
    target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
    target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
B
bellard 已提交
56
    target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
57
    int is_br;
58
    int mem_idx;
B
bellard 已提交
59
    int fpu_enabled;
60
    struct TranslationBlock *tb;
61 62
} DisasContext;

B
bellard 已提交
63 64
typedef struct sparc_def_t sparc_def_t;

B
blueswir1 已提交
65 66 67 68 69
struct sparc_def_t {
    const unsigned char *name;
    target_ulong iu_version;
    uint32_t fpu_version;
    uint32_t mmu_version;
70
    uint32_t mmu_bm;
71 72 73 74
    uint32_t mmu_ctpr_mask;
    uint32_t mmu_cxr_mask;
    uint32_t mmu_sfsr_mask;
    uint32_t mmu_trcr_mask;
B
blueswir1 已提交
75 76
};

B
bellard 已提交
77 78
static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name);

79 80 81
extern FILE *logfile;
extern int loglevel;

B
bellard 已提交
82
// This function uses non-native bit order
83 84 85
#define GET_FIELD(X, FROM, TO) \
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))

B
bellard 已提交
86 87 88 89 90
// 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)
B
blueswir1 已提交
91
#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
B
bellard 已提交
92 93

#ifdef TARGET_SPARC64
94
#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
B
blueswir1 已提交
95
#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
B
bellard 已提交
96
#else
97
#define DFPREG(r) (r & 0x1e)
B
blueswir1 已提交
98
#define QFPREG(r) (r & 0x1c)
B
bellard 已提交
99 100 101 102 103 104 105 106
#endif

static int sign_extend(int x, int len)
{
    len = 32 - len;
    return (x << len) >> len;
}

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

109
static void disas_sparc_insn(DisasContext * dc);
110

B
bellard 已提交
111 112
#ifdef TARGET_SPARC64
#define GEN32(func, NAME) \
B
blueswir1 已提交
113
static GenOpFunc * const NAME ## _table [64] = {                              \
B
bellard 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
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
132
#define GEN32(func, NAME) \
B
blueswir1 已提交
133
static GenOpFunc *const NAME ## _table [32] = {                               \
134 135 136 137 138 139 140 141 142 143 144 145 146
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 已提交
147
#endif
148 149 150 151 152 153 154 155 156 157 158 159

/* 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
blueswir1 已提交
160 161 162 163 164 165 166
#if defined(CONFIG_USER_ONLY)
GEN32(gen_op_load_fpr_QT0, gen_op_load_fpr_QT0_fprf);
GEN32(gen_op_load_fpr_QT1, gen_op_load_fpr_QT1_fprf);
GEN32(gen_op_store_QT0_fpr, gen_op_store_QT0_fpr_fprf);
GEN32(gen_op_store_QT1_fpr, gen_op_store_QT1_fpr_fprf);
#endif

167 168
/* moves */
#ifdef CONFIG_USER_ONLY
B
bellard 已提交
169
#define supervisor(dc) 0
170
#ifdef TARGET_SPARC64
B
blueswir1 已提交
171
#define hypervisor(dc) 0
172
#endif
B
bellard 已提交
173 174
#define gen_op_ldst(name)        gen_op_##name##_raw()
#else
B
blueswir1 已提交
175
#define supervisor(dc) (dc->mem_idx >= 1)
176 177
#ifdef TARGET_SPARC64
#define hypervisor(dc) (dc->mem_idx == 2)
B
blueswir1 已提交
178 179 180 181 182 183 184
#define OP_LD_TABLE(width)                                              \
    static GenOpFunc * const gen_op_##width[] = {                       \
        &gen_op_##width##_user,                                         \
        &gen_op_##width##_kernel,                                       \
        &gen_op_##width##_hypv,                                         \
    };
#else
B
blueswir1 已提交
185
#define OP_LD_TABLE(width)                                              \
B
blueswir1 已提交
186
    static GenOpFunc * const gen_op_##width[] = {                       \
B
blueswir1 已提交
187 188
        &gen_op_##width##_user,                                         \
        &gen_op_##width##_kernel,                                       \
189
    };
B
bellard 已提交
190
#endif
B
blueswir1 已提交
191 192
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
#endif
193

194
#ifndef CONFIG_USER_ONLY
B
blueswir1 已提交
195 196 197
#ifdef __i386__
OP_LD_TABLE(std);
#endif /* __i386__ */
198 199 200 201
OP_LD_TABLE(stf);
OP_LD_TABLE(stdf);
OP_LD_TABLE(ldf);
OP_LD_TABLE(lddf);
202 203
#endif

B
blueswir1 已提交
204 205 206 207 208
#ifdef TARGET_ABI32
#define ABI32_MASK(addr) tcg_gen_andi_i64(addr, addr, 0xffffffffULL);
#else
#define ABI32_MASK(addr)
#endif
209

B
blueswir1 已提交
210
static inline void gen_movl_simm_T1(int32_t val)
211
{
B
blueswir1 已提交
212
    tcg_gen_movi_tl(cpu_T[1], val);
213 214
}

B
blueswir1 已提交
215
static inline void gen_movl_reg_TN(int reg, TCGv tn)
216
{
B
blueswir1 已提交
217 218 219 220 221 222 223
    if (reg == 0)
        tcg_gen_movi_tl(tn, 0);
    else if (reg < 8)
        tcg_gen_ld_tl(tn, cpu_env, offsetof(CPUState, gregs[reg]));
    else {
        tcg_gen_ld_ptr(cpu_regwptr, cpu_env, offsetof(CPUState, regwptr)); // XXX
        tcg_gen_ld_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
224 225 226
    }
}

B
blueswir1 已提交
227
static inline void gen_movl_reg_T0(int reg)
228
{
B
blueswir1 已提交
229
    gen_movl_reg_TN(reg, cpu_T[0]);
230 231
}

B
blueswir1 已提交
232
static inline void gen_movl_reg_T1(int reg)
233
{
B
blueswir1 已提交
234
    gen_movl_reg_TN(reg, cpu_T[1]);
235 236
}

B
blueswir1 已提交
237 238 239 240 241 242 243
#ifdef __i386__
static inline void gen_movl_reg_T2(int reg)
{
    gen_movl_reg_TN(reg, cpu_T[2]);
}

#endif /* __i386__ */
B
blueswir1 已提交
244
static inline void gen_movl_TN_reg(int reg, TCGv tn)
245
{
B
blueswir1 已提交
246 247 248 249 250 251 252
    if (reg == 0)
        return;
    else if (reg < 8)
        tcg_gen_st_tl(tn, cpu_env, offsetof(CPUState, gregs[reg]));
    else {
        tcg_gen_ld_ptr(cpu_regwptr, cpu_env, offsetof(CPUState, regwptr)); // XXX
        tcg_gen_st_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
253 254 255
    }
}

B
blueswir1 已提交
256
static inline void gen_movl_T0_reg(int reg)
B
bellard 已提交
257
{
B
blueswir1 已提交
258
    gen_movl_TN_reg(reg, cpu_T[0]);
B
bellard 已提交
259 260
}

B
blueswir1 已提交
261
static inline void gen_movl_T1_reg(int reg)
B
bellard 已提交
262
{
B
blueswir1 已提交
263
    gen_movl_TN_reg(reg, cpu_T[1]);
B
bellard 已提交
264 265
}

B
blueswir1 已提交
266
static inline void gen_op_movl_T0_env(size_t offset)
267
{
B
blueswir1 已提交
268
    tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
269 270
}

B
blueswir1 已提交
271
static inline void gen_op_movl_env_T0(size_t offset)
272
{
B
blueswir1 已提交
273
    tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
274 275
}

B
blueswir1 已提交
276
static inline void gen_op_movtl_T0_env(size_t offset)
277
{
B
blueswir1 已提交
278
    tcg_gen_ld_tl(cpu_T[0], cpu_env, offset);
279 280
}

B
blueswir1 已提交
281
static inline void gen_op_movtl_env_T0(size_t offset)
282
{
B
blueswir1 已提交
283
    tcg_gen_st_tl(cpu_T[0], cpu_env, offset);
284 285
}

B
blueswir1 已提交
286
static inline void gen_op_add_T1_T0(void)
287
{
B
blueswir1 已提交
288
    tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
289 290
}

B
blueswir1 已提交
291
static inline void gen_op_or_T1_T0(void)
292
{
B
blueswir1 已提交
293
    tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
294 295
}

B
blueswir1 已提交
296
static inline void gen_op_xor_T1_T0(void)
297
{
B
blueswir1 已提交
298
    tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
299 300
}

B
bellard 已提交
301 302
static inline void gen_jmp_im(target_ulong pc)
{
B
blueswir1 已提交
303 304
    tcg_gen_movi_tl(cpu_tmp0, pc);
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, pc));
B
bellard 已提交
305 306 307 308
}

static inline void gen_movl_npc_im(target_ulong npc)
{
B
blueswir1 已提交
309 310
    tcg_gen_movi_tl(cpu_tmp0, npc);
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, npc));
B
bellard 已提交
311 312
}

313
static inline void gen_goto_tb(DisasContext *s, int tb_num,
314 315 316 317 318 319 320 321
                               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 */
B
bellard 已提交
322
        tcg_gen_goto_tb(tb_num);
323 324
        gen_jmp_im(pc);
        gen_movl_npc_im(npc);
B
bellard 已提交
325
        tcg_gen_exit_tb((long)tb + tb_num);
326 327 328 329
    } else {
        /* jump to another page: currently not optimized */
        gen_jmp_im(pc);
        gen_movl_npc_im(npc);
B
bellard 已提交
330
        tcg_gen_exit_tb(0);
331 332 333
    }
}

B
blueswir1 已提交
334 335
static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
                               target_ulong pc2)
B
bellard 已提交
336 337 338 339 340 341 342
{
    int l1;

    l1 = gen_new_label();

    gen_op_jz_T2_label(l1);

343
    gen_goto_tb(dc, 0, pc1, pc1 + 4);
B
bellard 已提交
344 345

    gen_set_label(l1);
346
    gen_goto_tb(dc, 1, pc2, pc2 + 4);
B
bellard 已提交
347 348
}

B
blueswir1 已提交
349 350
static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
                                target_ulong pc2)
B
bellard 已提交
351 352 353 354 355 356 357
{
    int l1;

    l1 = gen_new_label();

    gen_op_jz_T2_label(l1);

358
    gen_goto_tb(dc, 0, pc2, pc1);
B
bellard 已提交
359 360

    gen_set_label(l1);
361
    gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
B
bellard 已提交
362 363
}

B
blueswir1 已提交
364 365
static inline void gen_branch(DisasContext *dc, target_ulong pc,
                              target_ulong npc)
B
bellard 已提交
366
{
367
    gen_goto_tb(dc, 0, pc, npc);
B
bellard 已提交
368 369
}

B
blueswir1 已提交
370
static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2)
B
bellard 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
{
    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) {
B
blueswir1 已提交
390
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
391 392 393 394
        dc->npc = DYNAMIC_PC;
    }
}

B
bellard 已提交
395 396 397
static inline void save_npc(DisasContext * dc)
{
    if (dc->npc == JUMP_PC) {
B
blueswir1 已提交
398
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
399 400
        dc->npc = DYNAMIC_PC;
    } else if (dc->npc != DYNAMIC_PC) {
B
bellard 已提交
401
        gen_movl_npc_im(dc->npc);
B
bellard 已提交
402 403 404 405 406
    }
}

static inline void save_state(DisasContext * dc)
{
B
bellard 已提交
407
    gen_jmp_im(dc->pc);
B
bellard 已提交
408 409 410
    save_npc(dc);
}

B
bellard 已提交
411 412 413
static inline void gen_mov_pc_npc(DisasContext * dc)
{
    if (dc->npc == JUMP_PC) {
B
blueswir1 已提交
414
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
415 416
        tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, npc));
        tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, pc));
B
bellard 已提交
417 418
        dc->pc = DYNAMIC_PC;
    } else if (dc->npc == DYNAMIC_PC) {
419 420
        tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, npc));
        tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, pc));
B
bellard 已提交
421 422 423 424 425 426
        dc->pc = DYNAMIC_PC;
    } else {
        dc->pc = dc->npc;
    }
}

427 428 429 430 431 432 433 434
static inline void gen_op_next_insn(void)
{
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, npc));
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, pc));
    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, 4);
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, npc));
}

B
bellard 已提交
435 436
static GenOpFunc * const gen_cond[2][16] = {
    {
B
blueswir1 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
        gen_op_eval_bn,
        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,
        gen_op_eval_ba,
        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,
B
bellard 已提交
453 454 455
    },
    {
#ifdef TARGET_SPARC64
B
blueswir1 已提交
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
        gen_op_eval_bn,
        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,
        gen_op_eval_ba,
        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,
B
bellard 已提交
472 473 474 475 476 477
#endif
    },
};

static GenOpFunc * const gen_fcond[4][16] = {
    {
B
blueswir1 已提交
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
        gen_op_eval_bn,
        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,
        gen_op_eval_ba,
        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,
B
bellard 已提交
494 495 496
    },
#ifdef TARGET_SPARC64
    {
B
blueswir1 已提交
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
        gen_op_eval_bn,
        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,
        gen_op_eval_ba,
        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,
B
bellard 已提交
513 514
    },
    {
B
blueswir1 已提交
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
        gen_op_eval_bn,
        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,
        gen_op_eval_ba,
        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,
B
bellard 已提交
531 532
    },
    {
B
blueswir1 已提交
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
        gen_op_eval_bn,
        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,
        gen_op_eval_ba,
        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,
B
bellard 已提交
549 550 551 552 553
    },
#else
    {}, {}, {},
#endif
};
554

B
bellard 已提交
555 556
#ifdef TARGET_SPARC64
static void gen_cond_reg(int cond)
557
{
B
blueswir1 已提交
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
        switch (cond) {
        case 0x1:
            gen_op_eval_brz();
            break;
        case 0x2:
            gen_op_eval_brlez();
            break;
        case 0x3:
            gen_op_eval_brlz();
            break;
        case 0x5:
            gen_op_eval_brnz();
            break;
        case 0x6:
            gen_op_eval_brgz();
            break;
574
        default:
B
blueswir1 已提交
575 576 577 578
        case 0x7:
            gen_op_eval_brgez();
            break;
        }
579
}
580 581 582 583 584 585 586 587 588 589 590 591

// Inverted logic
static const int gen_tcg_cond_reg[8] = {
    -1,
    TCG_COND_NE,
    TCG_COND_GT,
    TCG_COND_GE,
    -1,
    TCG_COND_EQ,
    TCG_COND_LE,
    TCG_COND_LT,
};
B
bellard 已提交
592
#endif
593

B
bellard 已提交
594
/* XXX: potentially incorrect if dynamic npc */
B
bellard 已提交
595
static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
596
{
597
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
598
    target_ulong target = dc->pc + offset;
599

600
    if (cond == 0x0) {
B
blueswir1 已提交
601 602 603 604 605 606 607 608
        /* 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;
        }
609
    } else if (cond == 0x8) {
B
blueswir1 已提交
610 611 612 613 614 615 616 617
        /* unconditional taken */
        if (a) {
            dc->pc = target;
            dc->npc = dc->pc + 4;
        } else {
            dc->pc = dc->npc;
            dc->npc = target;
        }
618
    } else {
B
bellard 已提交
619
        flush_T2(dc);
B
bellard 已提交
620
        gen_cond[cc][cond]();
B
blueswir1 已提交
621 622
        if (a) {
            gen_branch_a(dc, target, dc->npc);
623
            dc->is_br = 1;
B
blueswir1 已提交
624
        } else {
625
            dc->pc = dc->npc;
B
bellard 已提交
626 627 628
            dc->jump_pc[0] = target;
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
B
blueswir1 已提交
629
        }
630
    }
631 632
}

B
bellard 已提交
633
/* XXX: potentially incorrect if dynamic npc */
B
bellard 已提交
634
static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
635 636
{
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
637 638
    target_ulong target = dc->pc + offset;

639
    if (cond == 0x0) {
B
blueswir1 已提交
640 641 642 643 644 645 646 647
        /* 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;
        }
648
    } else if (cond == 0x8) {
B
blueswir1 已提交
649 650 651 652 653 654 655 656
        /* unconditional taken */
        if (a) {
            dc->pc = target;
            dc->npc = dc->pc + 4;
        } else {
            dc->pc = dc->npc;
            dc->npc = target;
        }
657 658
    } else {
        flush_T2(dc);
B
bellard 已提交
659
        gen_fcond[cc][cond]();
B
blueswir1 已提交
660 661
        if (a) {
            gen_branch_a(dc, target, dc->npc);
662
            dc->is_br = 1;
B
blueswir1 已提交
663
        } else {
664 665 666 667
            dc->pc = dc->npc;
            dc->jump_pc[0] = target;
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
B
blueswir1 已提交
668
        }
669 670 671
    }
}

B
bellard 已提交
672 673 674
#ifdef TARGET_SPARC64
/* XXX: potentially incorrect if dynamic npc */
static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
675
{
B
bellard 已提交
676 677 678 679 680 681
    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
blueswir1 已提交
682 683
        gen_branch_a(dc, target, dc->npc);
        dc->is_br = 1;
B
bellard 已提交
684
    } else {
B
blueswir1 已提交
685 686 687 688
        dc->pc = dc->npc;
        dc->jump_pc[0] = target;
        dc->jump_pc[1] = dc->npc + 4;
        dc->npc = JUMP_PC;
B
bellard 已提交
689
    }
690 691
}

B
bellard 已提交
692
static GenOpFunc * const gen_fcmps[4] = {
693 694 695 696
    helper_fcmps,
    helper_fcmps_fcc1,
    helper_fcmps_fcc2,
    helper_fcmps_fcc3,
B
bellard 已提交
697 698 699
};

static GenOpFunc * const gen_fcmpd[4] = {
700 701 702 703
    helper_fcmpd,
    helper_fcmpd_fcc1,
    helper_fcmpd_fcc2,
    helper_fcmpd_fcc3,
B
bellard 已提交
704
};
705

B
blueswir1 已提交
706 707
#if defined(CONFIG_USER_ONLY)
static GenOpFunc * const gen_fcmpq[4] = {
708 709 710 711
    helper_fcmpq,
    helper_fcmpq_fcc1,
    helper_fcmpq_fcc2,
    helper_fcmpq_fcc3,
B
blueswir1 已提交
712 713 714
};
#endif

715
static GenOpFunc * const gen_fcmpes[4] = {
716 717 718 719
    helper_fcmpes,
    helper_fcmpes_fcc1,
    helper_fcmpes_fcc2,
    helper_fcmpes_fcc3,
720 721 722
};

static GenOpFunc * const gen_fcmped[4] = {
723 724 725 726
    helper_fcmped,
    helper_fcmped_fcc1,
    helper_fcmped_fcc2,
    helper_fcmped_fcc3,
727 728
};

B
blueswir1 已提交
729 730
#if defined(CONFIG_USER_ONLY)
static GenOpFunc * const gen_fcmpeq[4] = {
731 732 733 734
    helper_fcmpeq,
    helper_fcmpeq_fcc1,
    helper_fcmpeq_fcc2,
    helper_fcmpeq_fcc3,
B
blueswir1 已提交
735 736
};
#endif
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807

static inline void gen_op_fcmps(int fccno)
{
    tcg_gen_helper_0_0(gen_fcmps[fccno]);
}

static inline void gen_op_fcmpd(int fccno)
{
    tcg_gen_helper_0_0(gen_fcmpd[fccno]);
}

#if defined(CONFIG_USER_ONLY)
static inline void gen_op_fcmpq(int fccno)
{
    tcg_gen_helper_0_0(gen_fcmpq[fccno]);
}
#endif

static inline void gen_op_fcmpes(int fccno)
{
    tcg_gen_helper_0_0(gen_fcmpes[fccno]);
}

static inline void gen_op_fcmped(int fccno)
{
    tcg_gen_helper_0_0(gen_fcmped[fccno]);
}

#if defined(CONFIG_USER_ONLY)
static inline void gen_op_fcmpeq(int fccno)
{
    tcg_gen_helper_0_0(gen_fcmpeq[fccno]);
}
#endif

#else

static inline void gen_op_fcmps(int fccno)
{
    tcg_gen_helper_0_0(helper_fcmps);
}

static inline void gen_op_fcmpd(int fccno)
{
    tcg_gen_helper_0_0(helper_fcmpd);
}

#if defined(CONFIG_USER_ONLY)
static inline void gen_op_fcmpq(int fccno)
{
    tcg_gen_helper_0_0(helper_fcmpq);
}
#endif

static inline void gen_op_fcmpes(int fccno)
{
    tcg_gen_helper_0_0(helper_fcmpes);
}

static inline void gen_op_fcmped(int fccno)
{
    tcg_gen_helper_0_0(helper_fcmped);
}

#if defined(CONFIG_USER_ONLY)
static inline void gen_op_fcmpeq(int fccno)
{
    tcg_gen_helper_0_0(helper_fcmpeq);
}
#endif

B
bellard 已提交
808 809
#endif

B
blueswir1 已提交
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
static inline void gen_op_exception(int exception)
{
    TCGv r_except;

    r_except = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_except, exception);
    tcg_gen_helper_0_1(raise_exception, r_except);
}

static inline void gen_op_fpexception_im(int fsr_flags)
{
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, fsr));
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, ~FSR_FTT_MASK);
    tcg_gen_ori_tl(cpu_tmp0, cpu_tmp0, fsr_flags);
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, fsr));
    gen_op_exception(TT_FP_EXCP);
}

B
bellard 已提交
828 829 830 831 832 833 834 835 836 837 838 839 840
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;
}

841 842 843 844 845 846 847 848 849 850 851 852
static inline void gen_op_clear_ieee_excp_and_FTT(void)
{
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, fsr));
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, ~(FSR_FTT_MASK | FSR_CEXC_MASK));
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, fsr));
}

static inline void gen_clear_float_exceptions(void)
{
    tcg_gen_helper_0_0(helper_clear_float_exceptions);
}

B
blueswir1 已提交
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
/* asi moves */
#ifdef TARGET_SPARC64
static inline void gen_ld_asi(int insn, int size, int sign)
{
    int asi, offset;
    TCGv r_size, r_sign;

    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_sign = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_size, size);
    tcg_gen_movi_i32(r_sign, sign);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(cpu_T[1], asi);
    }
    tcg_gen_helper_1_4(helper_ld_asi, cpu_T[1], cpu_T[0], cpu_T[1], r_size,
                       r_sign);
}

static inline void gen_st_asi(int insn, int size)
{
    int asi, offset;
    TCGv r_asi, r_size;

    r_asi = tcg_temp_new(TCG_TYPE_I32);
    r_size = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_size, size);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(r_asi, asi);
    }
    tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], cpu_T[1], r_asi, r_size);
}

static inline void gen_ldf_asi(int insn, int size, int rd)
{
    int asi, offset;
    TCGv r_asi, r_size, r_rd;

    r_asi = tcg_temp_new(TCG_TYPE_I32);
    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_rd = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_size, size);
    tcg_gen_movi_i32(r_rd, rd);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(r_asi, asi);
    }
    tcg_gen_helper_0_4(helper_ldf_asi, cpu_T[0], r_asi, r_size, r_rd);
}

static inline void gen_stf_asi(int insn, int size, int rd)
{
    int asi, offset;
    TCGv r_asi, r_size, r_rd;

    r_asi = tcg_temp_new(TCG_TYPE_I32);
    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_rd = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_size, size);
    tcg_gen_movi_i32(r_rd, rd);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(r_asi, asi);
    }
    tcg_gen_helper_0_4(helper_stf_asi, cpu_T[0], r_asi, r_size, r_rd);
}

static inline void gen_swap_asi(int insn)
{
    int asi, offset;
    TCGv r_size, r_sign, r_temp;

    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_sign = tcg_temp_new(TCG_TYPE_I32);
    r_temp = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_size, 4);
    tcg_gen_movi_i32(r_sign, 0);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(cpu_T[1], asi);
    }
    tcg_gen_helper_1_4(helper_ld_asi, r_temp, cpu_T[0], cpu_T[1], r_size,
                       r_sign);
    tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], cpu_T[1], r_size, r_sign);
    tcg_gen_mov_i32(cpu_T[1], r_temp);
}

static inline void gen_ldda_asi(int insn)
{
    int asi, offset;
    TCGv r_size, r_sign, r_dword;

    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_sign = tcg_temp_new(TCG_TYPE_I32);
    r_dword = tcg_temp_new(TCG_TYPE_I64);
    tcg_gen_movi_i32(r_size, 8);
    tcg_gen_movi_i32(r_sign, 0);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(cpu_T[1], asi);
    }
    tcg_gen_helper_1_4(helper_ld_asi, r_dword, cpu_T[0], cpu_T[1], r_size,
                       r_sign);
    tcg_gen_trunc_i64_i32(cpu_T[0], r_dword);
    tcg_gen_shri_i64(r_dword, r_dword, 32);
    tcg_gen_trunc_i64_i32(cpu_T[1], r_dword);
}

static inline void gen_cas_asi(int insn, int rd)
{
    int asi, offset;
    TCGv r_val1, r_asi;

    r_val1 = tcg_temp_new(TCG_TYPE_I32);
    r_asi = tcg_temp_new(TCG_TYPE_I32);
    gen_movl_reg_TN(rd, r_val1);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(r_asi, asi);
    }
    tcg_gen_helper_1_4(helper_cas_asi, cpu_T[1], cpu_T[0], r_val1, cpu_T[1],
                       r_asi);
}

static inline void gen_casx_asi(int insn, int rd)
{
    int asi, offset;
    TCGv r_val1, r_asi;

    r_val1 = tcg_temp_new(TCG_TYPE_I64);
    r_asi = tcg_temp_new(TCG_TYPE_I32);
    gen_movl_reg_TN(rd, r_val1);
    if (IS_IMM) {
        offset = GET_FIELD(insn, 25, 31);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
        tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi));
    } else {
        asi = GET_FIELD(insn, 19, 26);
        tcg_gen_movi_i32(r_asi, asi);
    }
    tcg_gen_helper_1_4(helper_casx_asi, cpu_T[1], cpu_T[0], r_val1, cpu_T[1],
                       r_asi);
}

#elif !defined(CONFIG_USER_ONLY)

static inline void gen_ld_asi(int insn, int size, int sign)
{
    int asi;
    TCGv r_size, r_sign, r_dword;

    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_sign = tcg_temp_new(TCG_TYPE_I32);
    r_dword = tcg_temp_new(TCG_TYPE_I64);
    tcg_gen_movi_i32(r_size, size);
    tcg_gen_movi_i32(r_sign, sign);
    asi = GET_FIELD(insn, 19, 26);
    tcg_gen_movi_i32(cpu_T[1], asi);
    tcg_gen_helper_1_4(helper_ld_asi, r_dword, cpu_T[0], cpu_T[1], r_size,
                       r_sign);
    tcg_gen_trunc_i64_i32(cpu_T[1], r_dword);
}

static inline void gen_st_asi(int insn, int size)
{
    int asi;
    TCGv r_dword, r_asi, r_size;

    r_dword = tcg_temp_new(TCG_TYPE_I64);
    tcg_gen_extu_i32_i64(r_dword, cpu_T[1]);
    r_asi = tcg_temp_new(TCG_TYPE_I32);
    r_size = tcg_temp_new(TCG_TYPE_I32);
    asi = GET_FIELD(insn, 19, 26);
    tcg_gen_movi_i32(r_asi, asi);
    tcg_gen_movi_i32(r_size, size);
    tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], r_dword, r_asi, r_size);
}

static inline void gen_swap_asi(int insn)
{
    int asi;
    TCGv r_size, r_sign, r_temp;

    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_sign = tcg_temp_new(TCG_TYPE_I32);
    r_temp = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_movi_i32(r_size, 4);
    tcg_gen_movi_i32(r_sign, 0);
    asi = GET_FIELD(insn, 19, 26);
    tcg_gen_movi_i32(cpu_T[1], asi);
    tcg_gen_helper_1_4(helper_ld_asi, r_temp, cpu_T[0], cpu_T[1], r_size,
                       r_sign);
    tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], cpu_T[1], r_size, r_sign);
    tcg_gen_mov_i32(cpu_T[1], r_temp);
}

static inline void gen_ldda_asi(int insn)
{
    int asi;
    TCGv r_size, r_sign, r_dword;

    r_size = tcg_temp_new(TCG_TYPE_I32);
    r_sign = tcg_temp_new(TCG_TYPE_I32);
    r_dword = tcg_temp_new(TCG_TYPE_I64);
    tcg_gen_movi_i32(r_size, 8);
    tcg_gen_movi_i32(r_sign, 0);
    asi = GET_FIELD(insn, 19, 26);
    tcg_gen_movi_i32(cpu_T[1], asi);
    tcg_gen_helper_1_4(helper_ld_asi, r_dword, cpu_T[0], cpu_T[1], r_size,
                       r_sign);
    tcg_gen_trunc_i64_i32(cpu_T[0], r_dword);
    tcg_gen_shri_i64(r_dword, r_dword, 32);
    tcg_gen_trunc_i64_i32(cpu_T[1], r_dword);
}
#endif

#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
static inline void gen_ldstub_asi(int insn)
{
    int asi;
    TCGv r_dword, r_asi, r_size;

    gen_ld_asi(insn, 1, 0);

    r_dword = tcg_temp_new(TCG_TYPE_I64);
    r_asi = tcg_temp_new(TCG_TYPE_I32);
    r_size = tcg_temp_new(TCG_TYPE_I32);
    asi = GET_FIELD(insn, 19, 26);
    tcg_gen_movi_i32(r_dword, 0xff);
    tcg_gen_movi_i32(r_asi, asi);
    tcg_gen_movi_i32(r_size, 1);
    tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], r_dword, r_asi, r_size);
}
#endif

1117 1118 1119 1120 1121 1122 1123
static inline void gen_mov_reg_C(TCGv reg)
{
    tcg_gen_ld_i32(reg, cpu_env, offsetof(CPUSPARCState, psr));
    tcg_gen_shri_i32(reg, reg, 20);
    tcg_gen_andi_i32(reg, reg, 0x1);
}

B
bellard 已提交
1124
/* before an instruction, dc->pc must be static */
1125 1126 1127
static void disas_sparc_insn(DisasContext * dc)
{
    unsigned int insn, opc, rs1, rs2, rd;
1128

B
bellard 已提交
1129
    insn = ldl_code(dc->pc);
1130
    opc = GET_FIELD(insn, 0, 1);
1131

1132 1133
    rd = GET_FIELD(insn, 2, 6);
    switch (opc) {
B
blueswir1 已提交
1134 1135 1136 1137 1138
    case 0:                     /* branches/sethi */
        {
            unsigned int xop = GET_FIELD(insn, 7, 9);
            int32_t target;
            switch (xop) {
B
bellard 已提交
1139
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
            case 0x1:           /* V9 BPcc */
                {
                    int cc;

                    target = GET_FIELD_SP(insn, 0, 18);
                    target = sign_extend(target, 18);
                    target <<= 2;
                    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;
                }
            case 0x3:           /* V9 BPr */
                {
                    target = GET_FIELD_SP(insn, 0, 13) |
1159
                        (GET_FIELD_SP(insn, 20, 21) << 14);
B
blueswir1 已提交
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
                    target = sign_extend(target, 16);
                    target <<= 2;
                    rs1 = GET_FIELD(insn, 13, 17);
                    gen_movl_reg_T0(rs1);
                    do_branch_reg(dc, target, insn);
                    goto jmp_insn;
                }
            case 0x5:           /* V9 FBPcc */
                {
                    int cc = GET_FIELD_SP(insn, 20, 21);
B
bellard 已提交
1170 1171
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
B
blueswir1 已提交
1172 1173 1174 1175 1176 1177
                    target = GET_FIELD_SP(insn, 0, 18);
                    target = sign_extend(target, 19);
                    target <<= 2;
                    do_fbranch(dc, target, insn, cc);
                    goto jmp_insn;
                }
1178
#else
B
blueswir1 已提交
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
            case 0x7:           /* CBN+x */
                {
                    goto ncp_insn;
                }
#endif
            case 0x2:           /* BN+x */
                {
                    target = GET_FIELD(insn, 10, 31);
                    target = sign_extend(target, 22);
                    target <<= 2;
                    do_branch(dc, target, insn, 0);
                    goto jmp_insn;
                }
            case 0x6:           /* FBN+x */
                {
B
bellard 已提交
1194 1195
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
B
blueswir1 已提交
1196 1197 1198 1199 1200 1201 1202
                    target = GET_FIELD(insn, 10, 31);
                    target = sign_extend(target, 22);
                    target <<= 2;
                    do_fbranch(dc, target, insn, 0);
                    goto jmp_insn;
                }
            case 0x4:           /* SETHI */
B
bellard 已提交
1203 1204
#define OPTIM
#if defined(OPTIM)
B
blueswir1 已提交
1205
                if (rd) { // nop
B
bellard 已提交
1206
#endif
B
blueswir1 已提交
1207
                    uint32_t value = GET_FIELD(insn, 10, 31);
B
blueswir1 已提交
1208
                    tcg_gen_movi_tl(cpu_T[0], value << 10);
B
blueswir1 已提交
1209
                    gen_movl_T0_reg(rd);
B
bellard 已提交
1210
#if defined(OPTIM)
B
blueswir1 已提交
1211
                }
B
bellard 已提交
1212
#endif
B
blueswir1 已提交
1213 1214 1215
                break;
            case 0x0:           /* UNIMPL */
            default:
B
bellard 已提交
1216
                goto illegal_insn;
B
blueswir1 已提交
1217 1218 1219 1220
            }
            break;
        }
        break;
1221
    case 1:
B
blueswir1 已提交
1222 1223
        /*CALL*/ {
            target_long target = GET_FIELDs(insn, 2, 31) << 2;
1224

B
blueswir1 已提交
1225
            tcg_gen_movi_tl(cpu_T[0], dc->pc);
B
blueswir1 已提交
1226 1227
            gen_movl_T0_reg(15);
            target += dc->pc;
B
bellard 已提交
1228
            gen_mov_pc_npc(dc);
B
blueswir1 已提交
1229 1230 1231 1232 1233 1234 1235
            dc->npc = target;
        }
        goto jmp_insn;
    case 2:                     /* FPU & Logical Operations */
        {
            unsigned int xop = GET_FIELD(insn, 7, 12);
            if (xop == 0x3a) {  /* generate trap */
1236
                int cond;
B
bellard 已提交
1237

1238 1239
                rs1 = GET_FIELD(insn, 13, 17);
                gen_movl_reg_T0(rs1);
B
blueswir1 已提交
1240 1241
                if (IS_IMM) {
                    rs2 = GET_FIELD(insn, 25, 31);
B
blueswir1 已提交
1242
                    tcg_gen_addi_tl(cpu_T[0], cpu_T[0], rs2);
1243 1244
                } else {
                    rs2 = GET_FIELD(insn, 27, 31);
B
bellard 已提交
1245
#if defined(OPTIM)
B
blueswir1 已提交
1246
                    if (rs2 != 0) {
B
bellard 已提交
1247
#endif
B
blueswir1 已提交
1248 1249
                        gen_movl_reg_T1(rs2);
                        gen_op_add_T1_T0();
B
bellard 已提交
1250
#if defined(OPTIM)
B
blueswir1 已提交
1251
                    }
B
bellard 已提交
1252
#endif
1253 1254 1255
                }
                cond = GET_FIELD(insn, 3, 6);
                if (cond == 0x8) {
B
bellard 已提交
1256
                    save_state(dc);
B
blueswir1 已提交
1257
                    tcg_gen_helper_0_1(helper_trap, cpu_T[0]);
1258
                } else if (cond != 0) {
B
bellard 已提交
1259
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1260 1261 1262
                    /* V9 icc/xcc */
                    int cc = GET_FIELD_SP(insn, 11, 12);
                    flush_T2(dc);
B
bellard 已提交
1263
                    save_state(dc);
B
blueswir1 已提交
1264 1265 1266 1267 1268 1269
                    if (cc == 0)
                        gen_cond[0][cond]();
                    else if (cc == 2)
                        gen_cond[1][cond]();
                    else
                        goto illegal_insn;
B
bellard 已提交
1270
#else
B
blueswir1 已提交
1271
                    flush_T2(dc);
B
bellard 已提交
1272
                    save_state(dc);
B
blueswir1 已提交
1273
                    gen_cond[0][cond]();
B
bellard 已提交
1274
#endif
B
blueswir1 已提交
1275
                    tcg_gen_helper_0_2(helper_trapcc, cpu_T[0], cpu_T[2]);
1276
                }
B
bellard 已提交
1277
                gen_op_next_insn();
B
bellard 已提交
1278
                tcg_gen_exit_tb(0);
B
bellard 已提交
1279 1280
                dc->is_br = 1;
                goto jmp_insn;
1281 1282 1283 1284
            } else if (xop == 0x28) {
                rs1 = GET_FIELD(insn, 13, 17);
                switch(rs1) {
                case 0: /* rdy */
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
#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));
1296 1297
                    gen_movl_T0_reg(rd);
                    break;
B
bellard 已提交
1298
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1299
                case 0x2: /* V9 rdccr */
B
bellard 已提交
1300 1301 1302
                    gen_op_rdccr();
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
1303 1304
                case 0x3: /* V9 rdasi */
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
B
bellard 已提交
1305 1306
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
1307
                case 0x4: /* V9 rdtick */
B
blueswir1 已提交
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
                    {
                        TCGv r_tickptr;

                        r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, tick));
                        tcg_gen_helper_1_1(helper_tick_get_count, cpu_T[0],
                                           r_tickptr);
                        gen_movl_T0_reg(rd);
                    }
B
bellard 已提交
1318
                    break;
B
blueswir1 已提交
1319
                case 0x5: /* V9 rdpc */
B
blueswir1 已提交
1320
                    tcg_gen_movi_tl(cpu_T[0], dc->pc);
B
blueswir1 已提交
1321 1322 1323 1324
                    gen_movl_T0_reg(rd);
                    break;
                case 0x6: /* V9 rdfprs */
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
B
bellard 已提交
1325 1326
                    gen_movl_T0_reg(rd);
                    break;
1327 1328
                case 0xf: /* V9 membar */
                    break; /* no effect */
B
blueswir1 已提交
1329
                case 0x13: /* Graphics Status */
B
bellard 已提交
1330 1331
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
B
blueswir1 已提交
1332
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
B
bellard 已提交
1333 1334
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
1335 1336
                case 0x17: /* Tick compare */
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
B
bellard 已提交
1337 1338
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
1339
                case 0x18: /* System tick */
B
blueswir1 已提交
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
                    {
                        TCGv r_tickptr;

                        r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, stick));
                        tcg_gen_helper_1_1(helper_tick_get_count, cpu_T[0],
                                           r_tickptr);
                        gen_movl_T0_reg(rd);
                    }
B
bellard 已提交
1350
                    break;
B
blueswir1 已提交
1351 1352
                case 0x19: /* System tick compare */
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
B
bellard 已提交
1353 1354
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
1355 1356 1357 1358 1359 1360
                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 已提交
1361 1362
#endif
                default:
1363 1364
                    goto illegal_insn;
                }
1365
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
1366
            } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
B
bellard 已提交
1367
#ifndef TARGET_SPARC64
B
blueswir1 已提交
1368 1369
                if (!supervisor(dc))
                    goto priv_insn;
B
blueswir1 已提交
1370
                tcg_gen_helper_1_0(helper_rdpsr, cpu_T[0]);
B
blueswir1 已提交
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
#else
                if (!hypervisor(dc))
                    goto priv_insn;
                rs1 = GET_FIELD(insn, 13, 17);
                switch (rs1) {
                case 0: // hpstate
                    // gen_op_rdhpstate();
                    break;
                case 1: // htstate
                    // gen_op_rdhtstate();
                    break;
                case 3: // hintp
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, hintp));
                    break;
                case 5: // htba
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, htba));
                    break;
                case 6: // hver
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, hver));
                    break;
                case 31: // hstick_cmpr
                    gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
                    break;
                default:
                    goto illegal_insn;
                }
#endif
1398 1399
                gen_movl_T0_reg(rd);
                break;
B
bellard 已提交
1400
            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
B
blueswir1 已提交
1401 1402
                if (!supervisor(dc))
                    goto priv_insn;
B
bellard 已提交
1403 1404
#ifdef TARGET_SPARC64
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
1405 1406
                switch (rs1) {
                case 0: // tpc
1407 1408 1409 1410 1411 1412 1413 1414 1415
                    {
                        TCGv r_tsptr;

                        r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                       offsetof(CPUState, tsptr));
                        tcg_gen_ld_tl(cpu_T[0], r_tsptr,
                                      offsetof(trap_state, tpc));
                    }
B
blueswir1 已提交
1416 1417
                    break;
                case 1: // tnpc
1418 1419 1420 1421 1422 1423 1424 1425 1426
                    {
                        TCGv r_tsptr;

                        r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                       offsetof(CPUState, tsptr));
                        tcg_gen_ld_tl(cpu_T[0], r_tsptr,
                                      offsetof(trap_state, tnpc));
                    }
B
blueswir1 已提交
1427 1428
                    break;
                case 2: // tstate
1429 1430 1431 1432 1433 1434 1435 1436 1437
                    {
                        TCGv r_tsptr;

                        r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                       offsetof(CPUState, tsptr));
                        tcg_gen_ld_tl(cpu_T[0], r_tsptr,
                                      offsetof(trap_state, tstate));
                    }
B
blueswir1 已提交
1438 1439
                    break;
                case 3: // tt
1440 1441 1442 1443 1444 1445 1446 1447 1448
                    {
                        TCGv r_tsptr;

                        r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                       offsetof(CPUState, tsptr));
                        tcg_gen_ld_i32(cpu_T[0], r_tsptr,
                                       offsetof(trap_state, tt));
                    }
B
blueswir1 已提交
1449 1450
                    break;
                case 4: // tick
B
blueswir1 已提交
1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
                    {
                        TCGv r_tickptr;

                        r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, tick));
                        tcg_gen_helper_1_1(helper_tick_get_count, cpu_T[0],
                                           r_tickptr);
                        gen_movl_T0_reg(rd);
                    }
B
blueswir1 已提交
1461 1462 1463 1464 1465
                    break;
                case 5: // tba
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
                    break;
                case 6: // pstate
B
blueswir1 已提交
1466
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, pstate));
B
blueswir1 已提交
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
                    break;
                case 7: // tl
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
                    break;
                case 8: // pil
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
                    break;
                case 9: // cwp
                    gen_op_rdcwp();
                    break;
                case 10: // cansave
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
                    break;
                case 11: // canrestore
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
                    break;
                case 12: // cleanwin
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
                    break;
                case 13: // otherwin
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
                    break;
                case 14: // wstate
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
                    break;
B
blueswir1 已提交
1492 1493 1494 1495 1496 1497 1498 1499
                case 16: // UA2005 gl
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, gl));
                    break;
                case 26: // UA2005 strand status
                    if (!hypervisor(dc))
                        goto priv_insn;
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, ssr));
                    break;
B
blueswir1 已提交
1500 1501 1502 1503 1504 1505 1506
                case 31: // ver
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
                    break;
                case 15: // fq
                default:
                    goto illegal_insn;
                }
B
bellard 已提交
1507
#else
B
blueswir1 已提交
1508
                gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
B
bellard 已提交
1509
#endif
1510 1511
                gen_movl_T0_reg(rd);
                break;
B
bellard 已提交
1512 1513
            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1514
                gen_op_flushw();
B
bellard 已提交
1515
#else
B
blueswir1 已提交
1516 1517 1518
                if (!supervisor(dc))
                    goto priv_insn;
                gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1519
                gen_movl_T0_reg(rd);
B
bellard 已提交
1520
#endif
1521 1522
                break;
#endif
B
blueswir1 已提交
1523
            } else if (xop == 0x34) {   /* FPU Operations */
B
bellard 已提交
1524 1525
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
B
blueswir1 已提交
1526
                gen_op_clear_ieee_excp_and_FTT();
1527
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
                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);
1542
                        tcg_gen_helper_0_0(helper_fabss);
B
blueswir1 已提交
1543 1544 1545 1546
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x29: /* fsqrts */
                        gen_op_load_fpr_FT1(rs2);
1547 1548 1549
                        gen_clear_float_exceptions();
                        tcg_gen_helper_0_0(helper_fsqrts);
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1550 1551 1552 1553
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x2a: /* fsqrtd */
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1554 1555 1556
                        gen_clear_float_exceptions();
                        tcg_gen_helper_0_0(helper_fsqrtd);
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1557 1558 1559
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x2b: /* fsqrtq */
B
blueswir1 已提交
1560 1561
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1562 1563 1564
                        gen_clear_float_exceptions();
                        tcg_gen_helper_0_0(helper_fsqrtq);
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1565 1566 1567
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1568
                        goto nfpu_insn;
B
blueswir1 已提交
1569
#endif
B
blueswir1 已提交
1570 1571 1572
                    case 0x41:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
1573
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1574
                        gen_op_fadds();
1575
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1576 1577 1578 1579 1580
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x42:
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1581
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1582
                        gen_op_faddd();
1583
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1584 1585 1586
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x43: /* faddq */
B
blueswir1 已提交
1587 1588 1589
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1590
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1591
                        gen_op_faddq();
1592
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1593 1594 1595
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1596
                        goto nfpu_insn;
B
blueswir1 已提交
1597
#endif
B
blueswir1 已提交
1598 1599 1600
                    case 0x45:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
1601
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1602
                        gen_op_fsubs();
1603
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1604 1605 1606 1607 1608
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x46:
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1609
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1610
                        gen_op_fsubd();
1611
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1612 1613 1614
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x47: /* fsubq */
B
blueswir1 已提交
1615 1616 1617
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1618
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1619
                        gen_op_fsubq();
1620
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1621 1622 1623
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1624
                        goto nfpu_insn;
B
blueswir1 已提交
1625
#endif
B
blueswir1 已提交
1626 1627 1628
                    case 0x49:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
1629
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1630
                        gen_op_fmuls();
1631
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1632 1633 1634 1635 1636
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x4a:
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1637
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1638
                        gen_op_fmuld();
1639
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
1640
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
1641 1642
                        break;
                    case 0x4b: /* fmulq */
B
blueswir1 已提交
1643 1644 1645
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1646
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1647
                        gen_op_fmulq();
1648
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1649 1650 1651
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1652
                        goto nfpu_insn;
B
blueswir1 已提交
1653
#endif
B
blueswir1 已提交
1654 1655 1656
                    case 0x4d:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
1657
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1658
                        gen_op_fdivs();
1659
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1660 1661 1662 1663 1664
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x4e:
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1665
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1666
                        gen_op_fdivd();
1667
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1668 1669 1670
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x4f: /* fdivq */
B
blueswir1 已提交
1671 1672 1673
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1674
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1675
                        gen_op_fdivq();
1676
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1677 1678 1679
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1680
                        goto nfpu_insn;
B
blueswir1 已提交
1681
#endif
B
blueswir1 已提交
1682 1683 1684
                    case 0x69:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
1685
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1686
                        gen_op_fsmuld();
1687
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1688 1689 1690
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x6e: /* fdmulq */
B
blueswir1 已提交
1691 1692 1693
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1694
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1695
                        gen_op_fdmulq();
1696
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1697 1698 1699
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1700
                        goto nfpu_insn;
B
blueswir1 已提交
1701
#endif
B
blueswir1 已提交
1702 1703
                    case 0xc4:
                        gen_op_load_fpr_FT1(rs2);
1704
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1705
                        gen_op_fitos();
1706
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1707 1708 1709 1710
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0xc6:
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1711
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1712
                        gen_op_fdtos();
1713
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1714 1715 1716
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0xc7: /* fqtos */
B
blueswir1 已提交
1717 1718
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1719
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1720
                        gen_op_fqtos();
1721
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1722 1723 1724
                        gen_op_store_FT0_fpr(rd);
                        break;
#else
B
blueswir1 已提交
1725
                        goto nfpu_insn;
B
blueswir1 已提交
1726
#endif
B
blueswir1 已提交
1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737
                    case 0xc8:
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fitod();
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0xc9:
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fstod();
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0xcb: /* fqtod */
B
blueswir1 已提交
1738 1739
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1740
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1741
                        gen_op_fqtod();
1742
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1743 1744 1745
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1746
                        goto nfpu_insn;
B
blueswir1 已提交
1747
#endif
B
blueswir1 已提交
1748
                    case 0xcc: /* fitoq */
B
blueswir1 已提交
1749 1750 1751 1752 1753 1754
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fitoq();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1755
                        goto nfpu_insn;
B
blueswir1 已提交
1756
#endif
B
blueswir1 已提交
1757
                    case 0xcd: /* fstoq */
B
blueswir1 已提交
1758 1759 1760 1761 1762 1763
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fstoq();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1764
                        goto nfpu_insn;
B
blueswir1 已提交
1765
#endif
B
blueswir1 已提交
1766
                    case 0xce: /* fdtoq */
B
blueswir1 已提交
1767 1768 1769 1770 1771 1772
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_DT1(DFPREG(rs2));
                        gen_op_fdtoq();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1773
                        goto nfpu_insn;
B
blueswir1 已提交
1774
#endif
B
blueswir1 已提交
1775 1776
                    case 0xd1:
                        gen_op_load_fpr_FT1(rs2);
1777
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1778
                        gen_op_fstoi();
1779
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1780 1781 1782
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0xd2:
1783
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1784
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1785
                        gen_op_fdtoi();
1786
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1787 1788 1789
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0xd3: /* fqtoi */
B
blueswir1 已提交
1790 1791
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1792
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1793
                        gen_op_fqtoi();
1794
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1795 1796 1797
                        gen_op_store_FT0_fpr(rd);
                        break;
#else
B
blueswir1 已提交
1798
                        goto nfpu_insn;
B
blueswir1 已提交
1799
#endif
B
bellard 已提交
1800
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1801 1802 1803 1804
                    case 0x2: /* V9 fmovd */
                        gen_op_load_fpr_DT0(DFPREG(rs2));
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
B
blueswir1 已提交
1805 1806 1807 1808 1809 1810 1811 1812
                    case 0x3: /* V9 fmovq */
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs2));
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
                        goto nfpu_insn;
#endif
B
blueswir1 已提交
1813 1814 1815 1816 1817
                    case 0x6: /* V9 fnegd */
                        gen_op_load_fpr_DT1(DFPREG(rs2));
                        gen_op_fnegd();
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
B
blueswir1 已提交
1818 1819 1820 1821 1822 1823 1824 1825 1826
                    case 0x7: /* V9 fnegq */
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
                        gen_op_fnegq();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
                        goto nfpu_insn;
#endif
B
blueswir1 已提交
1827 1828
                    case 0xa: /* V9 fabsd */
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1829
                        tcg_gen_helper_0_0(helper_fabsd);
B
blueswir1 已提交
1830 1831
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
B
blueswir1 已提交
1832 1833 1834
                    case 0xb: /* V9 fabsq */
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1835
                        tcg_gen_helper_0_0(helper_fabsq);
B
blueswir1 已提交
1836 1837 1838 1839 1840
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
                        goto nfpu_insn;
#endif
B
blueswir1 已提交
1841 1842
                    case 0x81: /* V9 fstox */
                        gen_op_load_fpr_FT1(rs2);
1843
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1844
                        gen_op_fstox();
1845
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1846 1847 1848 1849
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x82: /* V9 fdtox */
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1850
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1851
                        gen_op_fdtox();
1852
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1853 1854
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
B
blueswir1 已提交
1855 1856 1857
                    case 0x83: /* V9 fqtox */
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT1(QFPREG(rs2));
1858
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1859
                        gen_op_fqtox();
1860
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1861 1862 1863 1864 1865
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
#else
                        goto nfpu_insn;
#endif
B
blueswir1 已提交
1866 1867
                    case 0x84: /* V9 fxtos */
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1868
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1869
                        gen_op_fxtos();
1870
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1871 1872 1873 1874
                        gen_op_store_FT0_fpr(rd);
                        break;
                    case 0x88: /* V9 fxtod */
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1875
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1876
                        gen_op_fxtod();
1877
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1878 1879 1880
                        gen_op_store_DT0_fpr(DFPREG(rd));
                        break;
                    case 0x8c: /* V9 fxtoq */
B
blueswir1 已提交
1881 1882
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1883
                        gen_clear_float_exceptions();
B
blueswir1 已提交
1884
                        gen_op_fxtoq();
1885
                        tcg_gen_helper_0_0(helper_check_ieee_exceptions);
B
blueswir1 已提交
1886 1887 1888
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1889
                        goto nfpu_insn;
B
blueswir1 已提交
1890
#endif
B
blueswir1 已提交
1891 1892 1893 1894 1895
#endif
                    default:
                        goto illegal_insn;
                }
            } else if (xop == 0x35) {   /* FPU Operations */
B
bellard 已提交
1896
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1897
                int cond;
B
bellard 已提交
1898
#endif
B
bellard 已提交
1899 1900
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
B
blueswir1 已提交
1901
                gen_op_clear_ieee_excp_and_FTT();
1902
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
1903 1904
                rs2 = GET_FIELD(insn, 27, 31);
                xop = GET_FIELD(insn, 18, 26);
B
bellard 已提交
1905
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1906
                if ((xop & 0x11f) == 0x005) { // V9 fmovsr
B
blueswir1 已提交
1907 1908 1909 1910 1911
                    TCGv r_zero;
                    int l1;

                    l1 = gen_new_label();
                    r_zero = tcg_temp_new(TCG_TYPE_TL);
B
blueswir1 已提交
1912 1913 1914
                    cond = GET_FIELD_SP(insn, 14, 17);
                    rs1 = GET_FIELD(insn, 13, 17);
                    gen_movl_reg_T0(rs1);
B
blueswir1 已提交
1915 1916 1917
                    tcg_gen_movi_tl(r_zero, 0);
                    tcg_gen_brcond_tl(gen_tcg_cond_reg[cond], cpu_T[0], r_zero, l1);
                    gen_op_load_fpr_FT1(rs2);
B
blueswir1 已提交
1918
                    gen_op_store_FT0_fpr(rd);
B
blueswir1 已提交
1919
                    gen_set_label(l1);
B
blueswir1 已提交
1920 1921
                    break;
                } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
B
blueswir1 已提交
1922 1923 1924 1925 1926
                    TCGv r_zero;
                    int l1;

                    l1 = gen_new_label();
                    r_zero = tcg_temp_new(TCG_TYPE_TL);
B
blueswir1 已提交
1927 1928 1929
                    cond = GET_FIELD_SP(insn, 14, 17);
                    rs1 = GET_FIELD(insn, 13, 17);
                    gen_movl_reg_T0(rs1);
B
blueswir1 已提交
1930 1931 1932
                    tcg_gen_movi_tl(r_zero, 0);
                    tcg_gen_brcond_tl(gen_tcg_cond_reg[cond], cpu_T[0], r_zero, l1);
                    gen_op_load_fpr_DT1(DFPREG(rs2));
1933
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
1934
                    gen_set_label(l1);
B
blueswir1 已提交
1935 1936
                    break;
                } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
B
blueswir1 已提交
1937
#if defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
1938 1939 1940 1941 1942
                    TCGv r_zero;
                    int l1;

                    l1 = gen_new_label();
                    r_zero = tcg_temp_new(TCG_TYPE_TL);
B
blueswir1 已提交
1943 1944 1945
                    cond = GET_FIELD_SP(insn, 14, 17);
                    rs1 = GET_FIELD(insn, 13, 17);
                    gen_movl_reg_T0(rs1);
B
blueswir1 已提交
1946 1947 1948
                    tcg_gen_movi_tl(r_zero, 0);
                    tcg_gen_brcond_tl(gen_tcg_cond_reg[cond], cpu_T[0], r_zero, l1);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
B
blueswir1 已提交
1949
                    gen_op_store_QT0_fpr(QFPREG(rd));
B
blueswir1 已提交
1950
                    gen_set_label(l1);
B
blueswir1 已提交
1951 1952
                    break;
#else
B
blueswir1 已提交
1953
                    goto nfpu_insn;
B
blueswir1 已提交
1954
#endif
B
blueswir1 已提交
1955 1956 1957
                }
#endif
                switch (xop) {
B
bellard 已提交
1958
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
                    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);
1970 1971
                        gen_op_load_fpr_DT0(DFPREG(rd));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
1972 1973 1974
                        flush_T2(dc);
                        gen_fcond[0][cond]();
                        gen_op_fmovd_cc();
1975
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
1976 1977
                        break;
                    case 0x003: /* V9 fmovqcc %fcc0 */
B
blueswir1 已提交
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987
#if defined(CONFIG_USER_ONLY)
                        cond = GET_FIELD_SP(insn, 14, 17);
                        gen_op_load_fpr_QT0(QFPREG(rd));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
                        flush_T2(dc);
                        gen_fcond[0][cond]();
                        gen_op_fmovq_cc();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
1988
                        goto nfpu_insn;
B
blueswir1 已提交
1989
#endif
B
blueswir1 已提交
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
                    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);
2001 2002
                        gen_op_load_fpr_DT0(DFPREG(rd));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2003 2004 2005
                        flush_T2(dc);
                        gen_fcond[1][cond]();
                        gen_op_fmovd_cc();
2006
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2007 2008
                        break;
                    case 0x043: /* V9 fmovqcc %fcc1 */
B
blueswir1 已提交
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
#if defined(CONFIG_USER_ONLY)
                        cond = GET_FIELD_SP(insn, 14, 17);
                        gen_op_load_fpr_QT0(QFPREG(rd));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
                        flush_T2(dc);
                        gen_fcond[1][cond]();
                        gen_op_fmovq_cc();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
2019
                        goto nfpu_insn;
B
blueswir1 已提交
2020
#endif
B
blueswir1 已提交
2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
                    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);
2032 2033
                        gen_op_load_fpr_DT0(DFPREG(rd));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2034 2035 2036
                        flush_T2(dc);
                        gen_fcond[2][cond]();
                        gen_op_fmovd_cc();
2037
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2038 2039
                        break;
                    case 0x083: /* V9 fmovqcc %fcc2 */
B
blueswir1 已提交
2040 2041 2042 2043 2044 2045 2046 2047 2048 2049
#if defined(CONFIG_USER_ONLY)
                        cond = GET_FIELD_SP(insn, 14, 17);
                        gen_op_load_fpr_QT0(rd);
                        gen_op_load_fpr_QT1(rs2);
                        flush_T2(dc);
                        gen_fcond[2][cond]();
                        gen_op_fmovq_cc();
                        gen_op_store_QT0_fpr(rd);
                        break;
#else
B
blueswir1 已提交
2050
                        goto nfpu_insn;
B
blueswir1 已提交
2051
#endif
B
blueswir1 已提交
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
                    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);
2063 2064
                        gen_op_load_fpr_DT0(DFPREG(rd));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2065 2066 2067
                        flush_T2(dc);
                        gen_fcond[3][cond]();
                        gen_op_fmovd_cc();
2068
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2069 2070
                        break;
                    case 0x0c3: /* V9 fmovqcc %fcc3 */
B
blueswir1 已提交
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
#if defined(CONFIG_USER_ONLY)
                        cond = GET_FIELD_SP(insn, 14, 17);
                        gen_op_load_fpr_QT0(QFPREG(rd));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
                        flush_T2(dc);
                        gen_fcond[3][cond]();
                        gen_op_fmovq_cc();
                        gen_op_store_QT0_fpr(QFPREG(rd));
                        break;
#else
B
blueswir1 已提交
2081
                        goto nfpu_insn;
B
blueswir1 已提交
2082
#endif
B
blueswir1 已提交
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
                    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);
2094 2095
                        gen_op_load_fpr_DT0(DFPREG(rd));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2096 2097 2098
                        flush_T2(dc);
                        gen_cond[0][cond]();
                        gen_op_fmovd_cc();
2099
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2100 2101
                        break;
                    case 0x103: /* V9 fmovqcc %icc */
B
blueswir1 已提交
2102 2103 2104 2105 2106 2107 2108 2109 2110 2111
#if defined(CONFIG_USER_ONLY)
                        cond = GET_FIELD_SP(insn, 14, 17);
                        gen_op_load_fpr_QT0(rd);
                        gen_op_load_fpr_QT1(rs2);
                        flush_T2(dc);
                        gen_cond[0][cond]();
                        gen_op_fmovq_cc();
                        gen_op_store_QT0_fpr(rd);
                        break;
#else
B
blueswir1 已提交
2112
                        goto nfpu_insn;
B
blueswir1 已提交
2113
#endif
B
blueswir1 已提交
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124
                    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);
2125 2126
                        gen_op_load_fpr_DT0(DFPREG(rd));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2127 2128 2129
                        flush_T2(dc);
                        gen_cond[1][cond]();
                        gen_op_fmovd_cc();
2130
                        gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2131 2132
                        break;
                    case 0x183: /* V9 fmovqcc %xcc */
B
blueswir1 已提交
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142
#if defined(CONFIG_USER_ONLY)
                        cond = GET_FIELD_SP(insn, 14, 17);
                        gen_op_load_fpr_QT0(rd);
                        gen_op_load_fpr_QT1(rs2);
                        flush_T2(dc);
                        gen_cond[1][cond]();
                        gen_op_fmovq_cc();
                        gen_op_store_QT0_fpr(rd);
                        break;
#else
B
blueswir1 已提交
2143 2144
                        goto nfpu_insn;
#endif
B
blueswir1 已提交
2145 2146
#endif
                    case 0x51: /* fcmps, V9 %fcc */
B
blueswir1 已提交
2147 2148
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
2149
                        gen_op_fcmps(rd & 3);
B
blueswir1 已提交
2150
                        break;
B
blueswir1 已提交
2151
                    case 0x52: /* fcmpd, V9 %fcc */
B
blueswir1 已提交
2152 2153
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
2154
                        gen_op_fcmpd(rd & 3);
B
blueswir1 已提交
2155
                        break;
B
blueswir1 已提交
2156 2157 2158 2159
                    case 0x53: /* fcmpq, V9 %fcc */
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
2160
                        gen_op_fcmpq(rd & 3);
B
blueswir1 已提交
2161 2162
                        break;
#else /* !defined(CONFIG_USER_ONLY) */
B
blueswir1 已提交
2163
                        goto nfpu_insn;
B
blueswir1 已提交
2164
#endif
B
blueswir1 已提交
2165 2166 2167
                    case 0x55: /* fcmpes, V9 %fcc */
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
2168
                        gen_op_fcmpes(rd & 3);
B
blueswir1 已提交
2169 2170 2171 2172
                        break;
                    case 0x56: /* fcmped, V9 %fcc */
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
2173
                        gen_op_fcmped(rd & 3);
B
blueswir1 已提交
2174
                        break;
B
blueswir1 已提交
2175 2176 2177 2178
                    case 0x57: /* fcmpeq, V9 %fcc */
#if defined(CONFIG_USER_ONLY)
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
2179
                        gen_op_fcmpeq(rd & 3);
B
blueswir1 已提交
2180 2181
                        break;
#else/* !defined(CONFIG_USER_ONLY) */
B
blueswir1 已提交
2182
                        goto nfpu_insn;
B
blueswir1 已提交
2183
#endif
B
blueswir1 已提交
2184 2185 2186
                    default:
                        goto illegal_insn;
                }
B
bellard 已提交
2187
#if defined(OPTIM)
B
blueswir1 已提交
2188 2189
            } else if (xop == 0x2) {
                // clr/mov shortcut
B
bellard 已提交
2190 2191

                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2192
                if (rs1 == 0) {
B
blueswir1 已提交
2193
                    // or %g0, x, y -> mov T0, x; mov y, T0
B
blueswir1 已提交
2194 2195
                    if (IS_IMM) {       /* immediate */
                        rs2 = GET_FIELDs(insn, 19, 31);
B
blueswir1 已提交
2196
                        tcg_gen_movi_tl(cpu_T[0], (int)rs2);
B
blueswir1 已提交
2197 2198
                    } else {            /* register */
                        rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
2199
                        gen_movl_reg_T0(rs2);
B
blueswir1 已提交
2200 2201 2202 2203 2204
                    }
                } else {
                    gen_movl_reg_T0(rs1);
                    if (IS_IMM) {       /* immediate */
                        rs2 = GET_FIELDs(insn, 19, 31);
B
blueswir1 已提交
2205
                        tcg_gen_ori_tl(cpu_T[0], cpu_T[0], (int)rs2);
B
blueswir1 已提交
2206 2207 2208 2209 2210 2211 2212 2213 2214
                    } 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();
                        }
                    }
                }
B
blueswir1 已提交
2215
                gen_movl_T0_reg(rd);
B
bellard 已提交
2216 2217
#endif
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2218
            } else if (xop == 0x25) { /* sll, V9 sllx */
B
bellard 已提交
2219
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2220 2221
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
B
bellard 已提交
2222
                    rs2 = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
2223 2224 2225 2226 2227 2228
                    if (insn & (1 << 12)) {
                        tcg_gen_shli_i64(cpu_T[0], cpu_T[0], rs2 & 0x3f);
                    } else {
                        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL);
                        tcg_gen_shli_i64(cpu_T[0], cpu_T[0], rs2 & 0x1f);
                    }
B
blueswir1 已提交
2229
                } else {                /* register */
B
bellard 已提交
2230 2231
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
B
blueswir1 已提交
2232 2233 2234 2235 2236 2237 2238 2239
                    if (insn & (1 << 12)) {
                        tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x3f);
                        tcg_gen_shl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
                    } else {
                        tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x1f);
                        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL);
                        tcg_gen_shl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
                    }
B
bellard 已提交
2240
                }
B
blueswir1 已提交
2241 2242
                gen_movl_T0_reg(rd);
            } else if (xop == 0x26) { /* srl, V9 srlx */
B
bellard 已提交
2243
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2244 2245
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
B
bellard 已提交
2246
                    rs2 = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
2247 2248 2249 2250 2251 2252
                    if (insn & (1 << 12)) {
                        tcg_gen_shri_i64(cpu_T[0], cpu_T[0], rs2 & 0x3f);
                    } else {
                        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL);
                        tcg_gen_shri_i64(cpu_T[0], cpu_T[0], rs2 & 0x1f);
                    }
B
blueswir1 已提交
2253
                } else {                /* register */
B
bellard 已提交
2254 2255
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
B
blueswir1 已提交
2256 2257 2258 2259 2260 2261 2262 2263
                    if (insn & (1 << 12)) {
                        tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x3f);
                        tcg_gen_shr_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
                    } else {
                        tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x1f);
                        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL);
                        tcg_gen_shr_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
                    }
B
bellard 已提交
2264
                }
B
blueswir1 已提交
2265 2266
                gen_movl_T0_reg(rd);
            } else if (xop == 0x27) { /* sra, V9 srax */
B
bellard 已提交
2267
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2268 2269
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
B
bellard 已提交
2270
                    rs2 = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
2271 2272 2273 2274 2275 2276 2277
                    if (insn & (1 << 12)) {
                        tcg_gen_sari_i64(cpu_T[0], cpu_T[0], rs2 & 0x3f);
                    } else {
                        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL);
                        tcg_gen_ext_i32_i64(cpu_T[0], cpu_T[0]);
                        tcg_gen_sari_i64(cpu_T[0], cpu_T[0], rs2 & 0x1f);
                    }
B
blueswir1 已提交
2278
                } else {                /* register */
B
bellard 已提交
2279 2280
                    rs2 = GET_FIELD(insn, 27, 31);
                    gen_movl_reg_T1(rs2);
B
blueswir1 已提交
2281 2282 2283 2284 2285 2286 2287 2288
                    if (insn & (1 << 12)) {
                        tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x3f);
                        tcg_gen_sar_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
                    } else {
                        tcg_gen_andi_i64(cpu_T[1], cpu_T[1], 0x1f);
                        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], 0xffffffffULL);
                        tcg_gen_sar_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
                    }
B
bellard 已提交
2289
                }
B
blueswir1 已提交
2290
                gen_movl_T0_reg(rd);
B
bellard 已提交
2291
#endif
2292
            } else if (xop < 0x36) {
B
bellard 已提交
2293
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2294 2295
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
2296
                    rs2 = GET_FIELDs(insn, 19, 31);
B
bellard 已提交
2297
                    gen_movl_simm_T1(rs2);
B
blueswir1 已提交
2298
                } else {                /* register */
2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310
                    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:
B
blueswir1 已提交
2311
                        tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
2312 2313 2314 2315
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x2:
B
blueswir1 已提交
2316
                        tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
blueswir1 已提交
2317 2318 2319
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
2320
                    case 0x3:
B
blueswir1 已提交
2321
                        tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
2322 2323 2324 2325 2326 2327 2328
                        if (xop & 0x10)
                            gen_op_logic_T0_cc();
                        break;
                    case 0x4:
                        if (xop & 0x10)
                            gen_op_sub_T1_T0_cc();
                        else
B
blueswir1 已提交
2329
                            tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347
                        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)
2348
                            gen_op_addx_T1_T0_cc();
2349 2350 2351 2352 2353
                        else {
                            gen_mov_reg_C(cpu_tmp0);
                            tcg_gen_add_tl(cpu_T[1], cpu_T[1], cpu_tmp0);
                            tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
                        }
2354
                        break;
P
pbrook 已提交
2355
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2356
                    case 0x9: /* V9 mulx */
B
blueswir1 已提交
2357
                        tcg_gen_mul_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
P
pbrook 已提交
2358 2359
                        break;
#endif
2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371
                    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)
2372
                            gen_op_subx_T1_T0_cc();
2373 2374 2375 2376 2377
                        else {
                            gen_mov_reg_C(cpu_tmp0);
                            tcg_gen_add_tl(cpu_T[1], cpu_T[1], cpu_tmp0);
                            tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
                        }
2378
                        break;
P
pbrook 已提交
2379
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2380
                    case 0xd: /* V9 udivx */
P
pbrook 已提交
2381 2382 2383
                        gen_op_udivx_T1_T0();
                        break;
#endif
2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396
                    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
blueswir1 已提交
2397
                    gen_movl_T0_reg(rd);
2398 2399
                } else {
                    switch (xop) {
B
blueswir1 已提交
2400 2401 2402 2403 2404 2405 2406 2407 2408
                    case 0x20: /* taddcc */
                        gen_op_tadd_T1_T0_cc();
                        gen_movl_T0_reg(rd);
                        break;
                    case 0x21: /* tsubcc */
                        gen_op_tsub_T1_T0_cc();
                        gen_movl_T0_reg(rd);
                        break;
                    case 0x22: /* taddcctv */
2409
                        save_state(dc);
B
blueswir1 已提交
2410 2411 2412 2413
                        gen_op_tadd_T1_T0_ccTV();
                        gen_movl_T0_reg(rd);
                        break;
                    case 0x23: /* tsubcctv */
2414
                        save_state(dc);
B
blueswir1 已提交
2415 2416 2417
                        gen_op_tsub_T1_T0_ccTV();
                        gen_movl_T0_reg(rd);
                        break;
2418 2419 2420 2421
                    case 0x24: /* mulscc */
                        gen_op_mulscc_T1_T0();
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
2422
#ifndef TARGET_SPARC64
B
blueswir1 已提交
2423
                    case 0x25:  /* sll */
B
blueswir1 已提交
2424 2425
                        tcg_gen_andi_i32(cpu_T[1], cpu_T[1], 0x1f);
                        tcg_gen_shl_i32(cpu_T[0], cpu_T[0], cpu_T[1]);
2426 2427
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
2428
                    case 0x26:  /* srl */
B
blueswir1 已提交
2429 2430
                        tcg_gen_andi_i32(cpu_T[1], cpu_T[1], 0x1f);
                        tcg_gen_shr_i32(cpu_T[0], cpu_T[0], cpu_T[1]);
2431 2432
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
2433
                    case 0x27:  /* sra */
B
blueswir1 已提交
2434 2435
                        tcg_gen_andi_i32(cpu_T[1], cpu_T[1], 0x1f);
                        tcg_gen_sar_i32(cpu_T[0], cpu_T[0], cpu_T[1]);
2436 2437
                        gen_movl_T0_reg(rd);
                        break;
B
bellard 已提交
2438
#endif
2439 2440 2441
                    case 0x30:
                        {
                            switch(rd) {
B
bellard 已提交
2442
                            case 0: /* wry */
B
blueswir1 已提交
2443 2444
                                gen_op_xor_T1_T0();
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
2445
                                break;
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456
#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
B
blueswir1 已提交
2457
                            case 0x2: /* V9 wrccr */
B
blueswir1 已提交
2458
                                gen_op_xor_T1_T0();
B
bellard 已提交
2459
                                gen_op_wrccr();
B
blueswir1 已提交
2460 2461
                                break;
                            case 0x3: /* V9 wrasi */
B
blueswir1 已提交
2462
                                gen_op_xor_T1_T0();
B
blueswir1 已提交
2463 2464 2465 2466 2467
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
                                break;
                            case 0x6: /* V9 wrfprs */
                                gen_op_xor_T1_T0();
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
2468 2469
                                save_state(dc);
                                gen_op_next_insn();
B
bellard 已提交
2470
                                tcg_gen_exit_tb(0);
2471
                                dc->is_br = 1;
B
blueswir1 已提交
2472 2473
                                break;
                            case 0xf: /* V9 sir, nop if user */
B
bellard 已提交
2474
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
2475
                                if (supervisor(dc))
B
blueswir1 已提交
2476
                                    ; // XXX
B
bellard 已提交
2477
#endif
B
blueswir1 已提交
2478 2479
                                break;
                            case 0x13: /* Graphics Status */
B
bellard 已提交
2480 2481
                                if (gen_trap_ifnofpu(dc))
                                    goto jmp_insn;
B
blueswir1 已提交
2482
                                gen_op_xor_T1_T0();
B
blueswir1 已提交
2483 2484 2485
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
                                break;
                            case 0x17: /* Tick compare */
B
bellard 已提交
2486
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
2487 2488
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
2489
#endif
B
blueswir1 已提交
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501
                                {
                                    TCGv r_tickptr;

                                    gen_op_xor_T1_T0();
                                    gen_op_movtl_env_T0(offsetof(CPUSPARCState,
                                                                 tick_cmpr));
                                    r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, tick));
                                    tcg_gen_helper_0_2(helper_tick_set_limit,
                                                       r_tickptr, cpu_T[0]);
                                }
B
blueswir1 已提交
2502 2503
                                break;
                            case 0x18: /* System tick */
B
bellard 已提交
2504
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
2505 2506
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
2507
#endif
B
blueswir1 已提交
2508 2509 2510 2511 2512 2513 2514 2515 2516 2517
                                {
                                    TCGv r_tickptr;

                                    gen_op_xor_T1_T0();
                                    r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, stick));
                                    tcg_gen_helper_0_2(helper_tick_set_count,
                                                       r_tickptr, cpu_T[0]);
                                }
B
blueswir1 已提交
2518 2519
                                break;
                            case 0x19: /* System tick compare */
B
bellard 已提交
2520
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
2521 2522
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
2523
#endif
B
blueswir1 已提交
2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535
                                {
                                    TCGv r_tickptr;

                                    gen_op_xor_T1_T0();
                                    gen_op_movtl_env_T0(offsetof(CPUSPARCState,
                                                                 stick_cmpr));
                                    r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, stick));
                                    tcg_gen_helper_0_2(helper_tick_set_limit,
                                                       r_tickptr, cpu_T[0]);
                                }
B
blueswir1 已提交
2536
                                break;
B
bellard 已提交
2537

B
blueswir1 已提交
2538 2539 2540 2541 2542 2543
                            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 已提交
2544
#endif
B
bellard 已提交
2545
                            default:
2546 2547 2548 2549
                                goto illegal_insn;
                            }
                        }
                        break;
2550
#if !defined(CONFIG_USER_ONLY)
2551
                    case 0x31: /* wrpsr, V9 saved, restored */
2552
                        {
B
blueswir1 已提交
2553 2554
                            if (!supervisor(dc))
                                goto priv_insn;
B
bellard 已提交
2555
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2556 2557 2558 2559 2560 2561 2562
                            switch (rd) {
                            case 0:
                                gen_op_saved();
                                break;
                            case 1:
                                gen_op_restored();
                                break;
B
blueswir1 已提交
2563 2564 2565 2566 2567
                            case 2: /* UA2005 allclean */
                            case 3: /* UA2005 otherw */
                            case 4: /* UA2005 normalw */
                            case 5: /* UA2005 invalw */
                                // XXX
B
blueswir1 已提交
2568
                            default:
B
bellard 已提交
2569 2570 2571
                                goto illegal_insn;
                            }
#else
2572
                            gen_op_xor_T1_T0();
B
blueswir1 已提交
2573
                            tcg_gen_helper_0_1(helper_wrpsr, cpu_T[0]);
B
bellard 已提交
2574 2575
                            save_state(dc);
                            gen_op_next_insn();
B
bellard 已提交
2576
                            tcg_gen_exit_tb(0);
B
blueswir1 已提交
2577
                            dc->is_br = 1;
B
bellard 已提交
2578
#endif
2579 2580
                        }
                        break;
2581
                    case 0x32: /* wrwim, V9 wrpr */
2582
                        {
B
blueswir1 已提交
2583 2584
                            if (!supervisor(dc))
                                goto priv_insn;
2585
                            gen_op_xor_T1_T0();
B
bellard 已提交
2586
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2587 2588
                            switch (rd) {
                            case 0: // tpc
2589 2590 2591 2592 2593 2594 2595 2596 2597
                                {
                                    TCGv r_tsptr;

                                    r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                   offsetof(CPUState, tsptr));
                                    tcg_gen_st_tl(cpu_T[0], r_tsptr,
                                                  offsetof(trap_state, tpc));
                                }
B
blueswir1 已提交
2598 2599
                                break;
                            case 1: // tnpc
2600 2601 2602 2603 2604 2605 2606 2607 2608
                                {
                                    TCGv r_tsptr;

                                    r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                   offsetof(CPUState, tsptr));
                                    tcg_gen_st_tl(cpu_T[0], r_tsptr,
                                                  offsetof(trap_state, tnpc));
                                }
B
blueswir1 已提交
2609 2610
                                break;
                            case 2: // tstate
2611 2612 2613 2614 2615 2616 2617 2618 2619
                                {
                                    TCGv r_tsptr;

                                    r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                   offsetof(CPUState, tsptr));
                                    tcg_gen_st_tl(cpu_T[0], r_tsptr,
                                                  offsetof(trap_state, tstate));
                                }
B
blueswir1 已提交
2620 2621
                                break;
                            case 3: // tt
2622 2623 2624 2625 2626 2627 2628 2629 2630
                                {
                                    TCGv r_tsptr;

                                    r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                   offsetof(CPUState, tsptr));
                                    tcg_gen_st_i32(cpu_T[0], r_tsptr,
                                                   offsetof(trap_state, tt));
                                }
B
blueswir1 已提交
2631 2632
                                break;
                            case 4: // tick
B
blueswir1 已提交
2633 2634 2635 2636 2637 2638 2639 2640 2641
                                {
                                    TCGv r_tickptr;

                                    r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, tick));
                                    tcg_gen_helper_0_2(helper_tick_set_count,
                                                       r_tickptr, cpu_T[0]);
                                }
B
blueswir1 已提交
2642 2643 2644 2645 2646
                                break;
                            case 5: // tba
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
                                break;
                            case 6: // pstate
P
pbrook 已提交
2647
                                save_state(dc);
B
blueswir1 已提交
2648
                                tcg_gen_helper_0_1(helper_wrpstate, cpu_T[0]);
P
pbrook 已提交
2649
                                gen_op_next_insn();
B
bellard 已提交
2650
                                tcg_gen_exit_tb(0);
P
pbrook 已提交
2651
                                dc->is_br = 1;
B
blueswir1 已提交
2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676
                                break;
                            case 7: // tl
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
                                break;
                            case 8: // pil
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
                                break;
                            case 9: // cwp
                                gen_op_wrcwp();
                                break;
                            case 10: // cansave
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
                                break;
                            case 11: // canrestore
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
                                break;
                            case 12: // cleanwin
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
                                break;
                            case 13: // otherwin
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
                                break;
                            case 14: // wstate
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
                                break;
B
blueswir1 已提交
2677 2678 2679 2680 2681 2682 2683 2684
                            case 16: // UA2005 gl
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, gl));
                                break;
                            case 26: // UA2005 strand status
                                if (!hypervisor(dc))
                                    goto priv_insn;
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, ssr));
                                break;
B
blueswir1 已提交
2685 2686 2687
                            default:
                                goto illegal_insn;
                            }
B
bellard 已提交
2688
#else
B
blueswir1 已提交
2689 2690
                            tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ((1 << NWINDOWS) - 1));
                            gen_op_movl_env_T0(offsetof(CPUSPARCState, wim));
B
bellard 已提交
2691
#endif
2692 2693
                        }
                        break;
B
blueswir1 已提交
2694
                    case 0x33: /* wrtbr, UA2005 wrhpr */
2695
                        {
B
blueswir1 已提交
2696
#ifndef TARGET_SPARC64
B
blueswir1 已提交
2697 2698
                            if (!supervisor(dc))
                                goto priv_insn;
2699
                            gen_op_xor_T1_T0();
B
blueswir1 已提交
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709
                            gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
#else
                            if (!hypervisor(dc))
                                goto priv_insn;
                            gen_op_xor_T1_T0();
                            switch (rd) {
                            case 0: // hpstate
                                // XXX gen_op_wrhpstate();
                                save_state(dc);
                                gen_op_next_insn();
B
bellard 已提交
2710
                                tcg_gen_exit_tb(0);
B
blueswir1 已提交
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722
                                dc->is_br = 1;
                                break;
                            case 1: // htstate
                                // XXX gen_op_wrhtstate();
                                break;
                            case 3: // hintp
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, hintp));
                                break;
                            case 5: // htba
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
                                break;
                            case 31: // hstick_cmpr
B
blueswir1 已提交
2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733
                                {
                                    TCGv r_tickptr;

                                    gen_op_movtl_env_T0(offsetof(CPUSPARCState,
                                                                 hstick_cmpr));
                                    r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, hstick));
                                    tcg_gen_helper_0_2(helper_tick_set_limit,
                                                       r_tickptr, cpu_T[0]);
                                }
B
blueswir1 已提交
2734 2735 2736 2737 2738 2739
                                break;
                            case 6: // hver readonly
                            default:
                                goto illegal_insn;
                            }
#endif
2740 2741 2742
                        }
                        break;
#endif
B
bellard 已提交
2743
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2744 2745 2746 2747
                    case 0x2c: /* V9 movcc */
                        {
                            int cc = GET_FIELD_SP(insn, 11, 12);
                            int cond = GET_FIELD_SP(insn, 14, 17);
2748 2749 2750
                            TCGv r_zero;
                            int l1;

B
blueswir1 已提交
2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761
                            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]();
                            }
2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776

                            l1 = gen_new_label();

                            r_zero = tcg_temp_new(TCG_TYPE_TL);
                            tcg_gen_movi_tl(r_zero, 0);
                            tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[2], r_zero, l1);
                            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_T1_reg(rd);
                            gen_set_label(l1);
B
blueswir1 已提交
2777 2778 2779
                            break;
                        }
                    case 0x2d: /* V9 sdivx */
B
bellard 已提交
2780
                        gen_op_sdivx_T1_T0();
B
blueswir1 已提交
2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793
                        gen_movl_T0_reg(rd);
                        break;
                    case 0x2e: /* V9 popc */
                        {
                            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);
                            }
B
blueswir1 已提交
2794 2795
                            tcg_gen_helper_1_1(helper_popc, cpu_T[0],
                                               cpu_T[1]);
B
blueswir1 已提交
2796 2797 2798 2799 2800
                            gen_movl_T0_reg(rd);
                        }
                    case 0x2f: /* V9 movr */
                        {
                            int cond = GET_FIELD_SP(insn, 10, 12);
2801 2802 2803
                            TCGv r_zero;
                            int l1;

B
blueswir1 已提交
2804 2805
                            rs1 = GET_FIELD(insn, 13, 17);
                            gen_movl_reg_T0(rs1);
2806 2807 2808 2809 2810 2811

                            l1 = gen_new_label();

                            r_zero = tcg_temp_new(TCG_TYPE_TL);
                            tcg_gen_movi_tl(r_zero, 0);
                            tcg_gen_brcond_tl(gen_tcg_cond_reg[cond], cpu_T[0], r_zero, l1);
B
blueswir1 已提交
2812 2813 2814
                            if (IS_IMM) {       /* immediate */
                                rs2 = GET_FIELD_SPs(insn, 0, 9);
                                gen_movl_simm_T1(rs2);
2815
                            } else {
B
blueswir1 已提交
2816 2817 2818
                                rs2 = GET_FIELD_SP(insn, 0, 4);
                                gen_movl_reg_T1(rs2);
                            }
2819 2820
                            gen_movl_T1_reg(rd);
                            gen_set_label(l1);
B
blueswir1 已提交
2821 2822 2823 2824 2825 2826 2827
                            break;
                        }
#endif
                    default:
                        goto illegal_insn;
                    }
                }
2828 2829 2830 2831 2832
            } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
#ifdef TARGET_SPARC64
                int opf = GET_FIELD_SP(insn, 5, 13);
                rs1 = GET_FIELD(insn, 13, 17);
                rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
2833 2834
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
2835 2836

                switch (opf) {
B
blueswir1 已提交
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868
                case 0x000: /* VIS I edge8cc */
                case 0x001: /* VIS II edge8n */
                case 0x002: /* VIS I edge8lcc */
                case 0x003: /* VIS II edge8ln */
                case 0x004: /* VIS I edge16cc */
                case 0x005: /* VIS II edge16n */
                case 0x006: /* VIS I edge16lcc */
                case 0x007: /* VIS II edge16ln */
                case 0x008: /* VIS I edge32cc */
                case 0x009: /* VIS II edge32n */
                case 0x00a: /* VIS I edge32lcc */
                case 0x00b: /* VIS II edge32ln */
                    // XXX
                    goto illegal_insn;
                case 0x010: /* VIS I array8 */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_array8();
                    gen_movl_T0_reg(rd);
                    break;
                case 0x012: /* VIS I array16 */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_array16();
                    gen_movl_T0_reg(rd);
                    break;
                case 0x014: /* VIS I array32 */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_array32();
                    gen_movl_T0_reg(rd);
                    break;
2869 2870 2871 2872 2873 2874
                case 0x018: /* VIS I alignaddr */
                    gen_movl_reg_T0(rs1);
                    gen_movl_reg_T1(rs2);
                    gen_op_alignaddr();
                    gen_movl_T0_reg(rd);
                    break;
B
blueswir1 已提交
2875
                case 0x019: /* VIS II bmask */
2876 2877
                case 0x01a: /* VIS I alignaddrl */
                    // XXX
B
blueswir1 已提交
2878 2879
                    goto illegal_insn;
                case 0x020: /* VIS I fcmple16 */
2880 2881
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2882
                    gen_op_fcmple16();
2883
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2884 2885
                    break;
                case 0x022: /* VIS I fcmpne16 */
2886 2887
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2888
                    gen_op_fcmpne16();
2889
                    gen_op_store_DT0_fpr(DFPREG(rd));
2890
                    break;
B
blueswir1 已提交
2891
                case 0x024: /* VIS I fcmple32 */
2892 2893
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2894
                    gen_op_fcmple32();
2895
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2896 2897
                    break;
                case 0x026: /* VIS I fcmpne32 */
2898 2899
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2900
                    gen_op_fcmpne32();
2901
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2902 2903
                    break;
                case 0x028: /* VIS I fcmpgt16 */
2904 2905
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2906
                    gen_op_fcmpgt16();
2907
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2908 2909
                    break;
                case 0x02a: /* VIS I fcmpeq16 */
2910 2911
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2912
                    gen_op_fcmpeq16();
2913
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2914 2915
                    break;
                case 0x02c: /* VIS I fcmpgt32 */
2916 2917
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2918
                    gen_op_fcmpgt32();
2919
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2920 2921
                    break;
                case 0x02e: /* VIS I fcmpeq32 */
2922 2923
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2924
                    gen_op_fcmpeq32();
2925
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2926 2927
                    break;
                case 0x031: /* VIS I fmul8x16 */
2928 2929
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2930
                    gen_op_fmul8x16();
2931
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2932 2933
                    break;
                case 0x033: /* VIS I fmul8x16au */
2934 2935
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2936
                    gen_op_fmul8x16au();
2937
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2938 2939
                    break;
                case 0x035: /* VIS I fmul8x16al */
2940 2941
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2942
                    gen_op_fmul8x16al();
2943
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2944 2945
                    break;
                case 0x036: /* VIS I fmul8sux16 */
2946 2947
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2948
                    gen_op_fmul8sux16();
2949
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2950 2951
                    break;
                case 0x037: /* VIS I fmul8ulx16 */
2952 2953
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2954
                    gen_op_fmul8ulx16();
2955
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2956 2957
                    break;
                case 0x038: /* VIS I fmuld8sux16 */
2958 2959
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2960
                    gen_op_fmuld8sux16();
2961
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2962 2963
                    break;
                case 0x039: /* VIS I fmuld8ulx16 */
2964 2965
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2966
                    gen_op_fmuld8ulx16();
2967
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2968 2969 2970 2971 2972 2973 2974
                    break;
                case 0x03a: /* VIS I fpack32 */
                case 0x03b: /* VIS I fpack16 */
                case 0x03d: /* VIS I fpackfix */
                case 0x03e: /* VIS I pdist */
                    // XXX
                    goto illegal_insn;
2975
                case 0x048: /* VIS I faligndata */
2976 2977
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
2978
                    gen_op_faligndata();
2979
                    gen_op_store_DT0_fpr(DFPREG(rd));
2980
                    break;
B
blueswir1 已提交
2981
                case 0x04b: /* VIS I fpmerge */
2982 2983
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2984
                    gen_op_fpmerge();
2985
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2986 2987 2988 2989 2990
                    break;
                case 0x04c: /* VIS II bshuffle */
                    // XXX
                    goto illegal_insn;
                case 0x04d: /* VIS I fexpand */
2991 2992
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2993
                    gen_op_fexpand();
2994
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
2995 2996
                    break;
                case 0x050: /* VIS I fpadd16 */
2997 2998
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
2999
                    gen_op_fpadd16();
3000
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3001 3002 3003 3004 3005 3006 3007 3008
                    break;
                case 0x051: /* VIS I fpadd16s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpadd16s();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x052: /* VIS I fpadd32 */
3009 3010
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3011
                    gen_op_fpadd32();
3012
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3013 3014 3015 3016 3017 3018 3019 3020
                    break;
                case 0x053: /* VIS I fpadd32s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpadd32s();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x054: /* VIS I fpsub16 */
3021 3022
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3023
                    gen_op_fpsub16();
3024
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3025 3026 3027 3028 3029 3030 3031 3032
                    break;
                case 0x055: /* VIS I fpsub16s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpsub16s();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x056: /* VIS I fpsub32 */
3033 3034
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3035
                    gen_op_fpadd32();
3036
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3037 3038 3039 3040 3041 3042 3043
                    break;
                case 0x057: /* VIS I fpsub32s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fpsub32s();
                    gen_op_store_FT0_fpr(rd);
                    break;
3044 3045
                case 0x060: /* VIS I fzero */
                    gen_op_movl_DT0_0();
3046
                    gen_op_store_DT0_fpr(DFPREG(rd));
3047 3048 3049 3050 3051
                    break;
                case 0x061: /* VIS I fzeros */
                    gen_op_movl_FT0_0();
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
3052
                case 0x062: /* VIS I fnor */
3053 3054
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3055
                    gen_op_fnor();
3056
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3057 3058 3059 3060 3061 3062 3063 3064
                    break;
                case 0x063: /* VIS I fnors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fnors();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x064: /* VIS I fandnot2 */
3065 3066
                    gen_op_load_fpr_DT1(DFPREG(rs1));
                    gen_op_load_fpr_DT0(DFPREG(rs2));
B
blueswir1 已提交
3067
                    gen_op_fandnot();
3068
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3069 3070 3071 3072 3073 3074 3075 3076
                    break;
                case 0x065: /* VIS I fandnot2s */
                    gen_op_load_fpr_FT1(rs1);
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_fandnots();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x066: /* VIS I fnot2 */
3077
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3078
                    gen_op_fnot();
3079
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3080 3081 3082 3083 3084 3085 3086
                    break;
                case 0x067: /* VIS I fnot2s */
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fnot();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x068: /* VIS I fandnot1 */
3087 3088
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3089
                    gen_op_fandnot();
3090
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3091 3092 3093 3094 3095 3096 3097 3098
                    break;
                case 0x069: /* VIS I fandnot1s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fandnots();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x06a: /* VIS I fnot1 */
3099
                    gen_op_load_fpr_DT1(DFPREG(rs1));
B
blueswir1 已提交
3100
                    gen_op_fnot();
3101
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3102 3103 3104 3105 3106 3107 3108
                    break;
                case 0x06b: /* VIS I fnot1s */
                    gen_op_load_fpr_FT1(rs1);
                    gen_op_fnot();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x06c: /* VIS I fxor */
3109 3110
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3111
                    gen_op_fxor();
3112
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3113 3114 3115 3116 3117 3118 3119 3120
                    break;
                case 0x06d: /* VIS I fxors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fxors();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x06e: /* VIS I fnand */
3121 3122
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3123
                    gen_op_fnand();
3124
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3125 3126 3127 3128 3129 3130 3131 3132
                    break;
                case 0x06f: /* VIS I fnands */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fnands();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x070: /* VIS I fand */
3133 3134
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3135
                    gen_op_fand();
3136
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3137 3138 3139 3140 3141 3142 3143 3144
                    break;
                case 0x071: /* VIS I fands */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fands();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x072: /* VIS I fxnor */
3145 3146
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3147
                    gen_op_fxnor();
3148
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3149 3150 3151 3152 3153 3154 3155
                    break;
                case 0x073: /* VIS I fxnors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fxnors();
                    gen_op_store_FT0_fpr(rd);
                    break;
3156
                case 0x074: /* VIS I fsrc1 */
3157 3158
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_store_DT0_fpr(DFPREG(rd));
3159 3160 3161 3162 3163
                    break;
                case 0x075: /* VIS I fsrc1s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
3164
                case 0x076: /* VIS I fornot2 */
3165 3166
                    gen_op_load_fpr_DT1(DFPREG(rs1));
                    gen_op_load_fpr_DT0(DFPREG(rs2));
B
blueswir1 已提交
3167
                    gen_op_fornot();
3168
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3169 3170 3171 3172 3173 3174 3175
                    break;
                case 0x077: /* VIS I fornot2s */
                    gen_op_load_fpr_FT1(rs1);
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_fornots();
                    gen_op_store_FT0_fpr(rd);
                    break;
3176
                case 0x078: /* VIS I fsrc2 */
3177 3178
                    gen_op_load_fpr_DT0(DFPREG(rs2));
                    gen_op_store_DT0_fpr(DFPREG(rd));
3179 3180 3181 3182 3183
                    break;
                case 0x079: /* VIS I fsrc2s */
                    gen_op_load_fpr_FT0(rs2);
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
3184
                case 0x07a: /* VIS I fornot1 */
3185 3186
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3187
                    gen_op_fornot();
3188
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3189 3190 3191 3192 3193 3194 3195 3196
                    break;
                case 0x07b: /* VIS I fornot1s */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fornots();
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x07c: /* VIS I for */
3197 3198
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
B
blueswir1 已提交
3199
                    gen_op_for();
3200
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3201 3202 3203 3204 3205 3206 3207
                    break;
                case 0x07d: /* VIS I fors */
                    gen_op_load_fpr_FT0(rs1);
                    gen_op_load_fpr_FT1(rs2);
                    gen_op_fors();
                    gen_op_store_FT0_fpr(rd);
                    break;
3208 3209
                case 0x07e: /* VIS I fone */
                    gen_op_movl_DT0_1();
3210
                    gen_op_store_DT0_fpr(DFPREG(rd));
3211 3212 3213 3214 3215
                    break;
                case 0x07f: /* VIS I fones */
                    gen_op_movl_FT0_1();
                    gen_op_store_FT0_fpr(rd);
                    break;
B
blueswir1 已提交
3216 3217 3218 3219
                case 0x080: /* VIS I shutdown */
                case 0x081: /* VIS II siam */
                    // XXX
                    goto illegal_insn;
3220 3221 3222 3223
                default:
                    goto illegal_insn;
                }
#else
B
blueswir1 已提交
3224
                goto ncp_insn;
3225 3226
#endif
            } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
3227
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3228
                goto illegal_insn;
3229
#else
B
blueswir1 已提交
3230
                goto ncp_insn;
3231
#endif
B
bellard 已提交
3232
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3233
            } else if (xop == 0x39) { /* V9 return */
B
bellard 已提交
3234
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
3235
                save_state(dc);
B
blueswir1 已提交
3236 3237 3238
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
                    rs2 = GET_FIELDs(insn, 19, 31);
B
blueswir1 已提交
3239
                    tcg_gen_addi_tl(cpu_T[0], cpu_T[0], (int)rs2);
B
blueswir1 已提交
3240
                } else {                /* register */
B
bellard 已提交
3241 3242
                    rs2 = GET_FIELD(insn, 27, 31);
#if defined(OPTIM)
B
blueswir1 已提交
3243
                    if (rs2) {
B
bellard 已提交
3244
#endif
B
blueswir1 已提交
3245 3246
                        gen_movl_reg_T1(rs2);
                        gen_op_add_T1_T0();
B
bellard 已提交
3247
#if defined(OPTIM)
B
blueswir1 已提交
3248
                    }
B
bellard 已提交
3249 3250
#endif
                }
B
blueswir1 已提交
3251 3252
                gen_op_restore();
                gen_mov_pc_npc(dc);
B
blueswir1 已提交
3253
                gen_op_check_align_T0_3();
B
blueswir1 已提交
3254
                tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUSPARCState, npc));
B
blueswir1 已提交
3255 3256
                dc->npc = DYNAMIC_PC;
                goto jmp_insn;
B
bellard 已提交
3257
#endif
B
blueswir1 已提交
3258
            } else {
B
bellard 已提交
3259
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
3260 3261 3262
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
                    rs2 = GET_FIELDs(insn, 19, 31);
B
blueswir1 已提交
3263
                    tcg_gen_addi_tl(cpu_T[0], cpu_T[0], (int)rs2);
B
blueswir1 已提交
3264
                } else {                /* register */
B
bellard 已提交
3265 3266
                    rs2 = GET_FIELD(insn, 27, 31);
#if defined(OPTIM)
B
blueswir1 已提交
3267
                    if (rs2) {
B
bellard 已提交
3268
#endif
B
blueswir1 已提交
3269 3270
                        gen_movl_reg_T1(rs2);
                        gen_op_add_T1_T0();
B
bellard 已提交
3271
#if defined(OPTIM)
B
blueswir1 已提交
3272
                    }
3273
#endif
3274
                }
B
blueswir1 已提交
3275 3276 3277 3278
                switch (xop) {
                case 0x38:      /* jmpl */
                    {
                        if (rd != 0) {
B
blueswir1 已提交
3279
                            tcg_gen_movi_tl(cpu_T[1], dc->pc);
B
blueswir1 已提交
3280 3281
                            gen_movl_T1_reg(rd);
                        }
B
bellard 已提交
3282
                        gen_mov_pc_npc(dc);
B
blueswir1 已提交
3283
                        gen_op_check_align_T0_3();
B
blueswir1 已提交
3284
                        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUSPARCState, npc));
B
blueswir1 已提交
3285 3286 3287
                        dc->npc = DYNAMIC_PC;
                    }
                    goto jmp_insn;
B
bellard 已提交
3288
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
B
blueswir1 已提交
3289 3290 3291 3292
                case 0x39:      /* rett, V9 return */
                    {
                        if (!supervisor(dc))
                            goto priv_insn;
B
bellard 已提交
3293
                        gen_mov_pc_npc(dc);
B
blueswir1 已提交
3294
                        gen_op_check_align_T0_3();
B
blueswir1 已提交
3295
                        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUSPARCState, npc));
B
blueswir1 已提交
3296
                        dc->npc = DYNAMIC_PC;
B
blueswir1 已提交
3297
                        tcg_gen_helper_0_0(helper_rett);
B
blueswir1 已提交
3298 3299 3300 3301
                    }
                    goto jmp_insn;
#endif
                case 0x3b: /* flush */
B
blueswir1 已提交
3302
                    tcg_gen_helper_0_1(helper_flush, cpu_T[0]);
B
blueswir1 已提交
3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313
                    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 已提交
3314
#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
B
blueswir1 已提交
3315 3316 3317 3318 3319 3320 3321 3322
                case 0x3e:      /* V9 done/retry */
                    {
                        switch (rd) {
                        case 0:
                            if (!supervisor(dc))
                                goto priv_insn;
                            dc->npc = DYNAMIC_PC;
                            dc->pc = DYNAMIC_PC;
B
blueswir1 已提交
3323
                            tcg_gen_helper_0_0(helper_done);
B
blueswir1 已提交
3324 3325 3326 3327 3328 3329
                            goto jmp_insn;
                        case 1:
                            if (!supervisor(dc))
                                goto priv_insn;
                            dc->npc = DYNAMIC_PC;
                            dc->pc = DYNAMIC_PC;
B
blueswir1 已提交
3330
                            tcg_gen_helper_0_0(helper_retry);
B
blueswir1 已提交
3331 3332 3333 3334 3335 3336 3337 3338 3339 3340
                            goto jmp_insn;
                        default:
                            goto illegal_insn;
                        }
                    }
                    break;
#endif
                default:
                    goto illegal_insn;
                }
3341
            }
B
blueswir1 已提交
3342 3343 3344 3345 3346 3347 3348
            break;
        }
        break;
    case 3:                     /* load/store instructions */
        {
            unsigned int xop = GET_FIELD(insn, 7, 12);
            rs1 = GET_FIELD(insn, 13, 17);
3349
            save_state(dc);
B
blueswir1 已提交
3350
            gen_movl_reg_T0(rs1);
3351 3352 3353 3354 3355 3356
            if (xop == 0x3c || xop == 0x3e)
            {
                rs2 = GET_FIELD(insn, 27, 31);
                gen_movl_reg_T1(rs2);
            }
            else if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
3357
                rs2 = GET_FIELDs(insn, 19, 31);
B
blueswir1 已提交
3358
                tcg_gen_addi_tl(cpu_T[0], cpu_T[0], (int)rs2);
B
blueswir1 已提交
3359 3360
            } else {            /* register */
                rs2 = GET_FIELD(insn, 27, 31);
B
bellard 已提交
3361
#if defined(OPTIM)
B
blueswir1 已提交
3362
                if (rs2 != 0) {
B
bellard 已提交
3363
#endif
B
blueswir1 已提交
3364 3365
                    gen_movl_reg_T1(rs2);
                    gen_op_add_T1_T0();
B
bellard 已提交
3366
#if defined(OPTIM)
B
blueswir1 已提交
3367
                }
B
bellard 已提交
3368
#endif
B
blueswir1 已提交
3369
            }
B
blueswir1 已提交
3370 3371 3372
            if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
                (xop > 0x17 && xop <= 0x1d ) ||
                (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
B
blueswir1 已提交
3373
                switch (xop) {
B
blueswir1 已提交
3374
                case 0x0:       /* load unsigned word */
B
blueswir1 已提交
3375
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3376 3377
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld32u(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3378 3379
                    break;
                case 0x1:       /* load unsigned byte */
B
blueswir1 已提交
3380 3381
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld8u(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3382 3383
                    break;
                case 0x2:       /* load unsigned halfword */
B
blueswir1 已提交
3384
                    gen_op_check_align_T0_1();
B
blueswir1 已提交
3385 3386
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld16u(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3387 3388 3389
                    break;
                case 0x3:       /* load double word */
                    if (rd & 1)
3390
                        goto illegal_insn;
B
blueswir1 已提交
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402
                    else {
                        TCGv r_dword;

                        r_dword = tcg_temp_new(TCG_TYPE_I64);
                        gen_op_check_align_T0_7();
                        ABI32_MASK(cpu_T[0]);
                        tcg_gen_qemu_ld64(r_dword, cpu_T[0], dc->mem_idx);
                        tcg_gen_trunc_i64_i32(cpu_T[0], r_dword);
                        gen_movl_T0_reg(rd + 1);
                        tcg_gen_shri_i64(r_dword, r_dword, 32);
                        tcg_gen_trunc_i64_i32(cpu_T[1], r_dword);
                    }
B
blueswir1 已提交
3403 3404
                    break;
                case 0x9:       /* load signed byte */
B
blueswir1 已提交
3405 3406
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld8s(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3407 3408
                    break;
                case 0xa:       /* load signed halfword */
B
blueswir1 已提交
3409
                    gen_op_check_align_T0_1();
B
blueswir1 已提交
3410 3411
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld16s(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3412 3413
                    break;
                case 0xd:       /* ldstub -- XXX: should be atomically */
B
blueswir1 已提交
3414 3415 3416 3417
                    tcg_gen_movi_i32(cpu_tmp0, 0xff);
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld8s(cpu_T[1], cpu_T[0], dc->mem_idx);
                    tcg_gen_qemu_st8(cpu_tmp0, cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3418 3419
                    break;
                case 0x0f:      /* swap register with memory. Also atomically */
B
blueswir1 已提交
3420
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3421
                    gen_movl_reg_T1(rd);
B
blueswir1 已提交
3422 3423 3424 3425
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld32u(cpu_tmp0, cpu_T[0], dc->mem_idx);
                    tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], dc->mem_idx);
                    tcg_gen_mov_i32(cpu_T[1], cpu_tmp0);
B
blueswir1 已提交
3426
                    break;
B
bellard 已提交
3427
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
B
blueswir1 已提交
3428
                case 0x10:      /* load word alternate */
B
bellard 已提交
3429
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3430 3431 3432 3433
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
3434
#endif
B
blueswir1 已提交
3435
                    gen_op_check_align_T0_3();
3436
                    gen_ld_asi(insn, 4, 0);
B
blueswir1 已提交
3437 3438
                    break;
                case 0x11:      /* load unsigned byte alternate */
B
bellard 已提交
3439
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3440 3441 3442 3443 3444
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
3445
                    gen_ld_asi(insn, 1, 0);
B
blueswir1 已提交
3446 3447
                    break;
                case 0x12:      /* load unsigned halfword alternate */
B
bellard 已提交
3448
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3449 3450 3451 3452
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
3453
#endif
B
blueswir1 已提交
3454
                    gen_op_check_align_T0_1();
3455
                    gen_ld_asi(insn, 2, 0);
B
blueswir1 已提交
3456 3457
                    break;
                case 0x13:      /* load double word alternate */
B
bellard 已提交
3458
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3459 3460 3461 3462
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
3463
#endif
B
blueswir1 已提交
3464
                    if (rd & 1)
3465
                        goto illegal_insn;
B
blueswir1 已提交
3466
                    gen_op_check_align_T0_7();
3467
                    gen_ldda_asi(insn);
B
blueswir1 已提交
3468 3469 3470
                    gen_movl_T0_reg(rd + 1);
                    break;
                case 0x19:      /* load signed byte alternate */
B
bellard 已提交
3471
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3472 3473 3474 3475 3476
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
3477
                    gen_ld_asi(insn, 1, 1);
B
blueswir1 已提交
3478 3479
                    break;
                case 0x1a:      /* load signed halfword alternate */
B
bellard 已提交
3480
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3481 3482 3483 3484
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
3485
#endif
B
blueswir1 已提交
3486
                    gen_op_check_align_T0_1();
3487
                    gen_ld_asi(insn, 2, 1);
B
blueswir1 已提交
3488 3489
                    break;
                case 0x1d:      /* ldstuba -- XXX: should be atomically */
B
bellard 已提交
3490
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3491 3492 3493 3494 3495
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
3496
                    gen_ldstub_asi(insn);
B
blueswir1 已提交
3497 3498
                    break;
                case 0x1f:      /* swap reg with alt. memory. Also atomically */
B
bellard 已提交
3499
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3500 3501 3502 3503
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
3504
#endif
B
blueswir1 已提交
3505
                    gen_op_check_align_T0_3();
3506 3507
                    gen_movl_reg_T1(rd);
                    gen_swap_asi(insn);
B
blueswir1 已提交
3508
                    break;
B
bellard 已提交
3509 3510

#ifndef TARGET_SPARC64
B
blueswir1 已提交
3511 3512 3513 3514
                case 0x30: /* ldc */
                case 0x31: /* ldcsr */
                case 0x33: /* lddc */
                    goto ncp_insn;
B
bellard 已提交
3515 3516 3517
#endif
#endif
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3518
                case 0x08: /* V9 ldsw */
B
blueswir1 已提交
3519
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3520 3521
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld32s(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3522 3523
                    break;
                case 0x0b: /* V9 ldx */
B
blueswir1 已提交
3524
                    gen_op_check_align_T0_7();
B
blueswir1 已提交
3525 3526
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_ld64(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3527 3528
                    break;
                case 0x18: /* V9 ldswa */
B
blueswir1 已提交
3529
                    gen_op_check_align_T0_3();
3530
                    gen_ld_asi(insn, 4, 1);
B
blueswir1 已提交
3531 3532
                    break;
                case 0x1b: /* V9 ldxa */
B
blueswir1 已提交
3533
                    gen_op_check_align_T0_7();
3534
                    gen_ld_asi(insn, 8, 0);
B
blueswir1 已提交
3535 3536 3537 3538
                    break;
                case 0x2d: /* V9 prefetch, no effect */
                    goto skip_move;
                case 0x30: /* V9 ldfa */
B
blueswir1 已提交
3539
                    gen_op_check_align_T0_3();
3540
                    gen_ldf_asi(insn, 4, rd);
3541
                    goto skip_move;
B
blueswir1 已提交
3542
                case 0x33: /* V9 lddfa */
3543
                    gen_op_check_align_T0_3();
3544
                    gen_ldf_asi(insn, 8, DFPREG(rd));
3545
                    goto skip_move;
B
blueswir1 已提交
3546 3547 3548
                case 0x3d: /* V9 prefetcha, no effect */
                    goto skip_move;
                case 0x32: /* V9 ldqfa */
B
blueswir1 已提交
3549 3550
#if defined(CONFIG_USER_ONLY)
                    gen_op_check_align_T0_3();
3551
                    gen_ldf_asi(insn, 16, QFPREG(rd));
B
blueswir1 已提交
3552 3553
                    goto skip_move;
#else
B
blueswir1 已提交
3554
                    goto nfpu_insn;
B
blueswir1 已提交
3555
#endif
B
blueswir1 已提交
3556 3557 3558 3559 3560
#endif
                default:
                    goto illegal_insn;
                }
                gen_movl_T1_reg(rd);
B
bellard 已提交
3561
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3562
            skip_move: ;
B
bellard 已提交
3563
#endif
B
blueswir1 已提交
3564
            } else if (xop >= 0x20 && xop < 0x24) {
B
bellard 已提交
3565 3566
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
B
blueswir1 已提交
3567 3568
                switch (xop) {
                case 0x20:      /* load fpreg */
B
blueswir1 已提交
3569
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3570 3571 3572 3573
                    gen_op_ldst(ldf);
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x21:      /* load fsr */
B
blueswir1 已提交
3574
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3575 3576
                    gen_op_ldst(ldf);
                    gen_op_ldfsr();
3577
                    tcg_gen_helper_0_0(helper_ldfsr);
B
blueswir1 已提交
3578 3579
                    break;
                case 0x22:      /* load quad fpreg */
B
blueswir1 已提交
3580 3581 3582 3583 3584 3585
#if defined(CONFIG_USER_ONLY)
                    gen_op_check_align_T0_7();
                    gen_op_ldst(ldqf);
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
#else
B
blueswir1 已提交
3586
                    goto nfpu_insn;
B
blueswir1 已提交
3587
#endif
B
blueswir1 已提交
3588
                case 0x23:      /* load double fpreg */
B
blueswir1 已提交
3589
                    gen_op_check_align_T0_7();
B
blueswir1 已提交
3590 3591 3592 3593 3594 3595 3596 3597 3598 3599
                    gen_op_ldst(lddf);
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                default:
                    goto illegal_insn;
                }
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
                       xop == 0xe || xop == 0x1e) {
                gen_movl_reg_T1(rd);
                switch (xop) {
B
blueswir1 已提交
3600
                case 0x4: /* store word */
B
blueswir1 已提交
3601
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3602 3603
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3604
                    break;
B
blueswir1 已提交
3605 3606 3607
                case 0x5: /* store byte */
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_st8(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3608
                    break;
B
blueswir1 已提交
3609
                case 0x6: /* store halfword */
B
blueswir1 已提交
3610
                    gen_op_check_align_T0_1();
B
blueswir1 已提交
3611 3612
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_st16(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3613
                    break;
B
blueswir1 已提交
3614
                case 0x7: /* store double word */
B
blueswir1 已提交
3615
                    if (rd & 1)
3616
                        goto illegal_insn;
B
blueswir1 已提交
3617
#ifndef __i386__
B
blueswir1 已提交
3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628
                    else {
                        TCGv r_dword, r_low;

                        gen_op_check_align_T0_7();
                        r_dword = tcg_temp_new(TCG_TYPE_I64);
                        r_low = tcg_temp_new(TCG_TYPE_I32);
                        gen_movl_reg_TN(rd + 1, r_low);
                        tcg_gen_helper_1_2(helper_pack64, r_dword, cpu_T[1],
                                           r_low);
                        tcg_gen_qemu_st64(r_dword, cpu_T[0], dc->mem_idx);
                    }
B
blueswir1 已提交
3629 3630 3631 3632 3633 3634
#else /* __i386__ */
                    gen_op_check_align_T0_7();
                    flush_T2(dc);
                    gen_movl_reg_T2(rd + 1);
                    gen_op_ldst(std);
#endif /* __i386__ */
B
blueswir1 已提交
3635
                    break;
B
bellard 已提交
3636
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
B
blueswir1 已提交
3637
                case 0x14: /* store word alternate */
B
bellard 已提交
3638
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3639 3640 3641 3642
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
3643 3644
#endif
                    gen_op_check_align_T0_3();
3645
                    gen_st_asi(insn, 4);
B
bellard 已提交
3646
                    break;
B
blueswir1 已提交
3647
                case 0x15: /* store byte alternate */
B
bellard 已提交
3648
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3649 3650 3651 3652
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
3653
#endif
3654
                    gen_st_asi(insn, 1);
B
bellard 已提交
3655
                    break;
B
blueswir1 已提交
3656
                case 0x16: /* store halfword alternate */
B
bellard 已提交
3657
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3658 3659 3660 3661
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
3662 3663
#endif
                    gen_op_check_align_T0_1();
3664
                    gen_st_asi(insn, 2);
B
bellard 已提交
3665
                    break;
B
blueswir1 已提交
3666
                case 0x17: /* store double word alternate */
B
bellard 已提交
3667
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3668 3669 3670 3671
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
3672
#endif
B
blueswir1 已提交
3673
                    if (rd & 1)
3674
                        goto illegal_insn;
B
blueswir1 已提交
3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702
                    else {
                        int asi;
                        TCGv r_dword, r_temp, r_size;

                        gen_op_check_align_T0_7();
                        r_dword = tcg_temp_new(TCG_TYPE_I64);
                        r_temp = tcg_temp_new(TCG_TYPE_I32);
                        r_size = tcg_temp_new(TCG_TYPE_I32);
                        gen_movl_reg_TN(rd + 1, r_temp);
                        tcg_gen_helper_1_2(helper_pack64, r_dword, cpu_T[1],
                                           r_temp);
#ifdef TARGET_SPARC64
                        if (IS_IMM) {
                            int offset;

                            offset = GET_FIELD(insn, 25, 31);
                            tcg_gen_addi_tl(cpu_T[0], cpu_T[0], offset);
                            tcg_gen_ld_i32(r_dword, cpu_env, offsetof(CPUSPARCState, asi));
                        } else {
#endif
                            asi = GET_FIELD(insn, 19, 26);
                            tcg_gen_movi_i32(r_temp, asi);
#ifdef TARGET_SPARC64
                        }
#endif
                        tcg_gen_movi_i32(r_size, 8);
                        tcg_gen_helper_0_4(helper_st_asi, cpu_T[0], r_dword, r_temp, r_size);
                    }
B
bellard 已提交
3703
                    break;
B
bellard 已提交
3704
#endif
B
bellard 已提交
3705
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3706
                case 0x0e: /* V9 stx */
B
blueswir1 已提交
3707
                    gen_op_check_align_T0_7();
B
blueswir1 已提交
3708 3709
                    ABI32_MASK(cpu_T[0]);
                    tcg_gen_qemu_st64(cpu_T[1], cpu_T[0], dc->mem_idx);
B
blueswir1 已提交
3710 3711
                    break;
                case 0x1e: /* V9 stxa */
B
blueswir1 已提交
3712
                    gen_op_check_align_T0_7();
3713
                    gen_st_asi(insn, 8);
B
blueswir1 已提交
3714
                    break;
B
bellard 已提交
3715
#endif
B
blueswir1 已提交
3716 3717 3718 3719
                default:
                    goto illegal_insn;
                }
            } else if (xop > 0x23 && xop < 0x28) {
B
bellard 已提交
3720 3721
                if (gen_trap_ifnofpu(dc))
                    goto jmp_insn;
B
blueswir1 已提交
3722 3723
                switch (xop) {
                case 0x24:
B
blueswir1 已提交
3724
                    gen_op_check_align_T0_3();
3725
                    gen_op_load_fpr_FT0(rd);
B
blueswir1 已提交
3726 3727 3728
                    gen_op_ldst(stf);
                    break;
                case 0x25: /* stfsr, V9 stxfsr */
B
blueswir1 已提交
3729 3730 3731
#ifdef CONFIG_USER_ONLY
                    gen_op_check_align_T0_3();
#endif
B
blueswir1 已提交
3732 3733 3734
                    gen_op_stfsr();
                    gen_op_ldst(stf);
                    break;
B
blueswir1 已提交
3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750
                case 0x26:
#ifdef TARGET_SPARC64
#if defined(CONFIG_USER_ONLY)
                    /* V9 stqf, store quad fpreg */
                    gen_op_check_align_T0_7();
                    gen_op_load_fpr_QT0(QFPREG(rd));
                    gen_op_ldst(stqf);
                    break;
#else
                    goto nfpu_insn;
#endif
#else /* !TARGET_SPARC64 */
                    /* stdfq, store floating point queue */
#if defined(CONFIG_USER_ONLY)
                    goto illegal_insn;
#else
B
blueswir1 已提交
3751 3752 3753 3754 3755
                    if (!supervisor(dc))
                        goto priv_insn;
                    if (gen_trap_ifnofpu(dc))
                        goto jmp_insn;
                    goto nfq_insn;
B
blueswir1 已提交
3756
#endif
B
blueswir1 已提交
3757 3758
#endif
                case 0x27:
B
blueswir1 已提交
3759
                    gen_op_check_align_T0_7();
B
bellard 已提交
3760
                    gen_op_load_fpr_DT0(DFPREG(rd));
B
blueswir1 已提交
3761 3762 3763 3764 3765 3766 3767
                    gen_op_ldst(stdf);
                    break;
                default:
                    goto illegal_insn;
                }
            } else if (xop > 0x33 && xop < 0x3f) {
                switch (xop) {
3768
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3769
                case 0x34: /* V9 stfa */
B
blueswir1 已提交
3770
                    gen_op_check_align_T0_3();
3771
                    gen_op_load_fpr_FT0(rd);
3772
                    gen_stf_asi(insn, 4, rd);
B
blueswir1 已提交
3773
                    break;
B
blueswir1 已提交
3774 3775 3776 3777
                case 0x36: /* V9 stqfa */
#if defined(CONFIG_USER_ONLY)
                    gen_op_check_align_T0_7();
                    gen_op_load_fpr_QT0(QFPREG(rd));
3778
                    gen_stf_asi(insn, 16, QFPREG(rd));
B
blueswir1 已提交
3779 3780 3781 3782
                    break;
#else
                    goto nfpu_insn;
#endif
B
blueswir1 已提交
3783
                case 0x37: /* V9 stdfa */
3784 3785
                    gen_op_check_align_T0_3();
                    gen_op_load_fpr_DT0(DFPREG(rd));
3786
                    gen_stf_asi(insn, 8, DFPREG(rd));
B
blueswir1 已提交
3787 3788
                    break;
                case 0x3c: /* V9 casa */
B
blueswir1 已提交
3789
                    gen_op_check_align_T0_3();
B
blueswir1 已提交
3790
                    gen_cas_asi(insn, rd);
3791
                    gen_movl_T1_reg(rd);
B
blueswir1 已提交
3792 3793
                    break;
                case 0x3e: /* V9 casxa */
B
blueswir1 已提交
3794
                    gen_op_check_align_T0_7();
B
blueswir1 已提交
3795
                    gen_casx_asi(insn, rd);
3796
                    gen_movl_T1_reg(rd);
B
blueswir1 已提交
3797
                    break;
3798
#else
B
blueswir1 已提交
3799 3800 3801 3802 3803 3804 3805 3806 3807
                case 0x34: /* stc */
                case 0x35: /* stcsr */
                case 0x36: /* stdcq */
                case 0x37: /* stdc */
                    goto ncp_insn;
#endif
                default:
                    goto illegal_insn;
                }
3808
            }
B
blueswir1 已提交
3809 3810 3811 3812
            else
                goto illegal_insn;
        }
        break;
3813 3814
    }
    /* default case for non jump instructions */
B
bellard 已提交
3815
    if (dc->npc == DYNAMIC_PC) {
B
blueswir1 已提交
3816 3817
        dc->pc = DYNAMIC_PC;
        gen_op_next_insn();
B
bellard 已提交
3818 3819
    } else if (dc->npc == JUMP_PC) {
        /* we can do a static jump */
B
blueswir1 已提交
3820
        gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1]);
B
bellard 已提交
3821 3822
        dc->is_br = 1;
    } else {
B
blueswir1 已提交
3823 3824
        dc->pc = dc->npc;
        dc->npc = dc->npc + 4;
3825
    }
B
bellard 已提交
3826
 jmp_insn:
3827 3828
    return;
 illegal_insn:
B
bellard 已提交
3829
    save_state(dc);
3830 3831
    gen_op_exception(TT_ILL_INSN);
    dc->is_br = 1;
3832
    return;
B
bellard 已提交
3833
#if !defined(CONFIG_USER_ONLY)
3834 3835 3836 3837
 priv_insn:
    save_state(dc);
    gen_op_exception(TT_PRIV_INSN);
    dc->is_br = 1;
B
bellard 已提交
3838 3839 3840 3841 3842
    return;
 nfpu_insn:
    save_state(dc);
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
    dc->is_br = 1;
3843
    return;
B
blueswir1 已提交
3844
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3845 3846 3847 3848 3849 3850
 nfq_insn:
    save_state(dc);
    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
    dc->is_br = 1;
    return;
#endif
B
blueswir1 已提交
3851
#endif
3852 3853 3854 3855 3856 3857 3858
#ifndef TARGET_SPARC64
 ncp_insn:
    save_state(dc);
    gen_op_exception(TT_NCP_INSN);
    dc->is_br = 1;
    return;
#endif
3859 3860
}

B
blueswir1 已提交
3861 3862 3863 3864
static void tcg_macro_func(TCGContext *s, int macro_id, const int *dead_args)
{
}

3865
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
B
blueswir1 已提交
3866
                                                 int spc, CPUSPARCState *env)
3867
{
B
bellard 已提交
3868
    target_ulong pc_start, last_pc;
3869 3870
    uint16_t *gen_opc_end;
    DisasContext dc1, *dc = &dc1;
3871
    int j, lj = -1;
3872 3873 3874

    memset(dc, 0, sizeof(DisasContext));
    dc->tb = tb;
B
bellard 已提交
3875
    pc_start = tb->pc;
3876
    dc->pc = pc_start;
B
bellard 已提交
3877
    last_pc = dc->pc;
B
bellard 已提交
3878
    dc->npc = (target_ulong) tb->cs_base;
B
blueswir1 已提交
3879 3880
    dc->mem_idx = cpu_mmu_index(env);
    dc->fpu_enabled = cpu_fpu_enabled(env);
3881 3882
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

B
blueswir1 已提交
3883 3884 3885
    cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL);
    cpu_regwptr = tcg_temp_new(TCG_TYPE_PTR); // XXX

3886
    do {
3887 3888 3889
        if (env->nb_breakpoints > 0) {
            for(j = 0; j < env->nb_breakpoints; j++) {
                if (env->breakpoints[j] == dc->pc) {
B
blueswir1 已提交
3890 3891
                    if (dc->pc != pc_start)
                        save_state(dc);
B
blueswir1 已提交
3892
                    tcg_gen_helper_0_0(helper_debug);
B
bellard 已提交
3893
                    tcg_gen_exit_tb(0);
B
blueswir1 已提交
3894
                    dc->is_br = 1;
B
bellard 已提交
3895
                    goto exit_gen_loop;
3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911
                }
            }
        }
        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;
            }
        }
B
blueswir1 已提交
3912 3913 3914 3915 3916 3917 3918 3919
        last_pc = dc->pc;
        disas_sparc_insn(dc);

        if (dc->is_br)
            break;
        /* if the next PC is different, we abort now */
        if (dc->pc != (last_pc + 4))
            break;
B
bellard 已提交
3920 3921 3922 3923
        /* 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 已提交
3924 3925 3926
        /* if single step mode, we generate only one instruction and
           generate an exception */
        if (env->singlestep_enabled) {
B
bellard 已提交
3927
            gen_jmp_im(dc->pc);
B
bellard 已提交
3928
            tcg_gen_exit_tb(0);
B
bellard 已提交
3929 3930
            break;
        }
3931
    } while ((gen_opc_ptr < gen_opc_end) &&
B
blueswir1 已提交
3932
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
B
bellard 已提交
3933 3934

 exit_gen_loop:
B
bellard 已提交
3935
    if (!dc->is_br) {
3936
        if (dc->pc != DYNAMIC_PC &&
B
bellard 已提交
3937 3938
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
            /* static PC and NPC: we can use direct chaining */
B
blueswir1 已提交
3939
            gen_branch(dc, dc->pc, dc->npc);
B
bellard 已提交
3940 3941
        } else {
            if (dc->pc != DYNAMIC_PC)
B
bellard 已提交
3942
                gen_jmp_im(dc->pc);
B
bellard 已提交
3943
            save_npc(dc);
B
bellard 已提交
3944
            tcg_gen_exit_tb(0);
B
bellard 已提交
3945 3946
        }
    }
3947
    *gen_opc_ptr = INDEX_op_end;
3948 3949 3950 3951 3952 3953 3954 3955 3956 3957
    if (spc) {
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
#if 0
        if (loglevel > 0) {
            page_dump(logfile);
        }
#endif
3958 3959
        gen_opc_jump_pc[0] = dc->jump_pc[0];
        gen_opc_jump_pc[1] = dc->jump_pc[1];
3960
    } else {
B
bellard 已提交
3961
        tb->size = last_pc + 4 - pc_start;
3962
    }
3963
#ifdef DEBUG_DISAS
B
bellard 已提交
3964
    if (loglevel & CPU_LOG_TB_IN_ASM) {
B
blueswir1 已提交
3965 3966 3967 3968
        fprintf(logfile, "--------------\n");
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
        fprintf(logfile, "\n");
3969
    }
3970
#endif
3971
    return 0;
3972 3973
}

3974
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
3975
{
3976
    return gen_intermediate_code_internal(tb, 0, env);
3977 3978
}

3979
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
3980
{
3981
    return gen_intermediate_code_internal(tb, 1, env);
3982 3983
}

B
bellard 已提交
3984 3985
void cpu_reset(CPUSPARCState *env)
{
B
bellard 已提交
3986
    tlb_flush(env, 1);
3987 3988 3989
    env->cwp = 0;
    env->wim = 1;
    env->regwptr = env->regbase + (env->cwp * 16);
3990
#if defined(CONFIG_USER_ONLY)
3991
    env->user_mode_only = 1;
3992
#ifdef TARGET_SPARC64
3993 3994 3995 3996
    env->cleanwin = NWINDOWS - 2;
    env->cansave = NWINDOWS - 2;
    env->pstate = PS_RMO | PS_PEF | PS_IE;
    env->asi = 0x82; // Primary no-fault
3997
#endif
3998
#else
B
blueswir1 已提交
3999
    env->psret = 0;
4000
    env->psrs = 1;
B
bellard 已提交
4001
    env->psrps = 1;
B
bellard 已提交
4002
#ifdef TARGET_SPARC64
B
bellard 已提交
4003
    env->pstate = PS_PRIV;
B
blueswir1 已提交
4004
    env->hpstate = HS_PRIV;
B
bellard 已提交
4005
    env->pc = 0x1fff0000000ULL;
4006
    env->tsptr = &env->ts[env->tl];
B
bellard 已提交
4007
#else
B
blueswir1 已提交
4008
    env->pc = 0;
B
blueswir1 已提交
4009
    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
4010
    env->mmuregs[0] |= env->mmu_bm;
B
bellard 已提交
4011
#endif
B
bellard 已提交
4012
    env->npc = env->pc + 4;
4013
#endif
B
bellard 已提交
4014 4015
}

B
bellard 已提交
4016
CPUSPARCState *cpu_sparc_init(const char *cpu_model)
B
bellard 已提交
4017 4018
{
    CPUSPARCState *env;
B
bellard 已提交
4019
    const sparc_def_t *def;
B
blueswir1 已提交
4020
    static int inited;
B
bellard 已提交
4021 4022 4023 4024

    def = cpu_sparc_find_by_name(cpu_model);
    if (!def)
        return NULL;
B
bellard 已提交
4025

B
bellard 已提交
4026 4027
    env = qemu_mallocz(sizeof(CPUSPARCState));
    if (!env)
B
blueswir1 已提交
4028
        return NULL;
B
bellard 已提交
4029
    cpu_exec_init(env);
4030
    env->cpu_model_str = cpu_model;
B
bellard 已提交
4031 4032 4033 4034
    env->version = def->iu_version;
    env->fsr = def->fpu_version;
#if !defined(TARGET_SPARC64)
    env->mmu_bm = def->mmu_bm;
4035 4036 4037 4038
    env->mmu_ctpr_mask = def->mmu_ctpr_mask;
    env->mmu_cxr_mask = def->mmu_cxr_mask;
    env->mmu_sfsr_mask = def->mmu_sfsr_mask;
    env->mmu_trcr_mask = def->mmu_trcr_mask;
B
bellard 已提交
4039 4040 4041
    env->mmuregs[0] |= def->mmu_version;
    cpu_sparc_set_id(env, 0);
#endif
B
blueswir1 已提交
4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063

    /* init various static tables */
    if (!inited) {
        inited = 1;

        tcg_set_macro_func(&tcg_ctx, tcg_macro_func);
        cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
        //#if TARGET_LONG_BITS > HOST_LONG_BITS
#ifdef TARGET_SPARC64
        cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
                                      TCG_AREG0, offsetof(CPUState, t0), "T0");
        cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
                                      TCG_AREG0, offsetof(CPUState, t1), "T1");
        cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL,
                                      TCG_AREG0, offsetof(CPUState, t2), "T2");
#else
        cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
        cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
        cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2");
#endif
    }

B
bellard 已提交
4064 4065 4066 4067 4068 4069 4070 4071 4072 4073
    cpu_reset(env);
    
    return env;
}

void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
{
#if !defined(TARGET_SPARC64)
    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
#endif
4074 4075
}

B
blueswir1 已提交
4076 4077
static const sparc_def_t sparc_defs[] = {
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112
    {
        .name = "Fujitsu Sparc64",
        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Fujitsu Sparc64 III",
        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Fujitsu Sparc64 IV",
        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Fujitsu Sparc64 V",
        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "TI UltraSparc I",
        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
B
blueswir1 已提交
4113 4114
    {
        .name = "TI UltraSparc II",
B
blueswir1 已提交
4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "TI UltraSparc IIi",
        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "TI UltraSparc IIe",
        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Sun UltraSparc III",
        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Sun UltraSparc III Cu",
        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Sun UltraSparc IIIi",
        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Sun UltraSparc IV",
        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Sun UltraSparc IV+",
        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "Sun UltraSparc IIIi+",
        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
    {
        .name = "NEC UltraSparc I",
        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
B
blueswir1 已提交
4179 4180 4181 4182 4183
                       | (MAXTL << 8) | (NWINDOWS - 1)),
        .fpu_version = 0x00000000,
        .mmu_version = 0,
    },
#else
B
blueswir1 已提交
4184 4185 4186 4187 4188 4189
    {
        .name = "Fujitsu MB86900",
        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
        .mmu_bm = 0x00004000,
4190 4191 4192 4193
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4194
    },
B
blueswir1 已提交
4195 4196 4197 4198 4199
    {
        .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 */
4200
        .mmu_bm = 0x00004000,
4201 4202 4203 4204
        .mmu_ctpr_mask = 0x00ffffc0,
        .mmu_cxr_mask = 0x000000ff,
        .mmu_sfsr_mask = 0x00016fff,
        .mmu_trcr_mask = 0x00ffffff,
B
blueswir1 已提交
4205
    },
B
blueswir1 已提交
4206
    {
B
blueswir1 已提交
4207 4208 4209 4210
        .name = "Fujitsu MB86907",
        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
4211
        .mmu_bm = 0x00004000,
4212 4213 4214 4215
        .mmu_ctpr_mask = 0xffffffc0,
        .mmu_cxr_mask = 0x000000ff,
        .mmu_sfsr_mask = 0x00016fff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4216
    },
B
blueswir1 已提交
4217 4218 4219 4220 4221 4222
    {
        .name = "LSI L64811",
        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
        .mmu_version = 0x10 << 24,
        .mmu_bm = 0x00004000,
4223 4224 4225 4226
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4227 4228 4229 4230 4231 4232 4233
    },
    {
        .name = "Cypress CY7C601",
        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
        .mmu_version = 0x10 << 24,
        .mmu_bm = 0x00004000,
4234 4235 4236 4237
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4238 4239 4240 4241 4242 4243 4244
    },
    {
        .name = "Cypress CY7C611",
        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
        .mmu_version = 0x10 << 24,
        .mmu_bm = 0x00004000,
4245 4246 4247 4248
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4249 4250 4251 4252 4253 4254 4255
    },
    {
        .name = "TI SuperSparc II",
        .iu_version = 0x40000000,
        .fpu_version = 0 << 17,
        .mmu_version = 0x04000000,
        .mmu_bm = 0x00002000,
4256 4257 4258 4259
        .mmu_ctpr_mask = 0xffffffc0,
        .mmu_cxr_mask = 0x0000ffff,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4260
    },
B
blueswir1 已提交
4261 4262 4263 4264 4265
    {
        .name = "TI MicroSparc I",
        .iu_version = 0x41000000,
        .fpu_version = 4 << 17,
        .mmu_version = 0x41000000,
4266
        .mmu_bm = 0x00004000,
4267 4268 4269 4270
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0x00016fff,
        .mmu_trcr_mask = 0x0000003f,
B
blueswir1 已提交
4271 4272
    },
    {
B
blueswir1 已提交
4273 4274 4275 4276 4277
        .name = "TI MicroSparc II",
        .iu_version = 0x42000000,
        .fpu_version = 4 << 17,
        .mmu_version = 0x02000000,
        .mmu_bm = 0x00004000,
4278 4279
        .mmu_ctpr_mask = 0x00ffffc0,
        .mmu_cxr_mask = 0x000000ff,
4280
        .mmu_sfsr_mask = 0x00016fff,
4281
        .mmu_trcr_mask = 0x00ffffff,
B
blueswir1 已提交
4282 4283 4284 4285 4286 4287 4288
    },
    {
        .name = "TI MicroSparc IIep",
        .iu_version = 0x42000000,
        .fpu_version = 4 << 17,
        .mmu_version = 0x04000000,
        .mmu_bm = 0x00004000,
4289 4290 4291 4292
        .mmu_ctpr_mask = 0x00ffffc0,
        .mmu_cxr_mask = 0x000000ff,
        .mmu_sfsr_mask = 0x00016bff,
        .mmu_trcr_mask = 0x00ffffff,
B
blueswir1 已提交
4293 4294 4295 4296
    },
    {
        .name = "TI SuperSparc 51",
        .iu_version = 0x43000000,
B
blueswir1 已提交
4297 4298
        .fpu_version = 0 << 17,
        .mmu_version = 0x04000000,
4299
        .mmu_bm = 0x00002000,
4300 4301 4302 4303
        .mmu_ctpr_mask = 0xffffffc0,
        .mmu_cxr_mask = 0x0000ffff,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4304 4305
    },
    {
B
blueswir1 已提交
4306 4307 4308 4309 4310
        .name = "TI SuperSparc 61",
        .iu_version = 0x44000000,
        .fpu_version = 0 << 17,
        .mmu_version = 0x04000000,
        .mmu_bm = 0x00002000,
4311 4312 4313 4314
        .mmu_ctpr_mask = 0xffffffc0,
        .mmu_cxr_mask = 0x0000ffff,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4315 4316 4317
    },
    {
        .name = "Ross RT625",
B
blueswir1 已提交
4318 4319
        .iu_version = 0x1e000000,
        .fpu_version = 1 << 17,
B
blueswir1 已提交
4320 4321
        .mmu_version = 0x1e000000,
        .mmu_bm = 0x00004000,
4322 4323 4324 4325
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4326 4327 4328 4329 4330 4331 4332
    },
    {
        .name = "Ross RT620",
        .iu_version = 0x1f000000,
        .fpu_version = 1 << 17,
        .mmu_version = 0x1f000000,
        .mmu_bm = 0x00004000,
4333 4334 4335 4336
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4337 4338 4339 4340 4341 4342 4343
    },
    {
        .name = "BIT B5010",
        .iu_version = 0x20000000,
        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
        .mmu_version = 0x20000000,
        .mmu_bm = 0x00004000,
4344 4345 4346 4347
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4348 4349 4350 4351 4352 4353 4354
    },
    {
        .name = "Matsushita MN10501",
        .iu_version = 0x50000000,
        .fpu_version = 0 << 17,
        .mmu_version = 0x50000000,
        .mmu_bm = 0x00004000,
4355 4356 4357 4358
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4359 4360 4361 4362 4363 4364 4365
    },
    {
        .name = "Weitek W8601",
        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
        .mmu_version = 0x10 << 24,
        .mmu_bm = 0x00004000,
4366 4367 4368 4369
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4370 4371 4372 4373 4374 4375 4376
    },
    {
        .name = "LEON2",
        .iu_version = 0xf2000000,
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
        .mmu_version = 0xf2000000,
        .mmu_bm = 0x00004000,
4377 4378 4379 4380
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4381 4382 4383 4384 4385 4386
    },
    {
        .name = "LEON3",
        .iu_version = 0xf3000000,
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
        .mmu_version = 0xf3000000,
4387
        .mmu_bm = 0x00004000,
4388 4389 4390 4391
        .mmu_ctpr_mask = 0x007ffff0,
        .mmu_cxr_mask = 0x0000003f,
        .mmu_sfsr_mask = 0xffffffff,
        .mmu_trcr_mask = 0xffffffff,
B
blueswir1 已提交
4392
    },
B
blueswir1 已提交
4393 4394 4395
#endif
};

B
bellard 已提交
4396
static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name)
B
blueswir1 已提交
4397 4398 4399 4400 4401
{
    unsigned int i;

    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
B
bellard 已提交
4402
            return &sparc_defs[i];
B
blueswir1 已提交
4403 4404
        }
    }
B
bellard 已提交
4405
    return NULL;
B
blueswir1 已提交
4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420
}

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

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

4423
void cpu_dump_state(CPUState *env, FILE *f,
B
bellard 已提交
4424 4425
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                    int flags)
4426
{
4427 4428
    int i, x;

4429
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
B
bellard 已提交
4430
    cpu_fprintf(f, "General Registers:\n");
4431
    for (i = 0; i < 4; i++)
B
blueswir1 已提交
4432
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
B
bellard 已提交
4433
    cpu_fprintf(f, "\n");
4434
    for (; i < 8; i++)
B
blueswir1 已提交
4435
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
B
bellard 已提交
4436
    cpu_fprintf(f, "\nCurrent Register Window:\n");
4437
    for (x = 0; x < 3; x++) {
B
blueswir1 已提交
4438 4439 4440 4441 4442 4443 4444 4445 4446 4447
        for (i = 0; i < 4; i++)
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
                    env->regwptr[i + x * 8]);
        cpu_fprintf(f, "\n");
        for (; i < 8; i++)
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
                    env->regwptr[i + x * 8]);
        cpu_fprintf(f, "\n");
4448
    }
B
bellard 已提交
4449
    cpu_fprintf(f, "\nFloating Point Registers:\n");
4450 4451
    for (i = 0; i < 32; i++) {
        if ((i & 3) == 0)
B
bellard 已提交
4452 4453
            cpu_fprintf(f, "%%f%02d:", i);
        cpu_fprintf(f, " %016lf", env->fpr[i]);
4454
        if ((i & 3) == 3)
B
bellard 已提交
4455
            cpu_fprintf(f, "\n");
4456
    }
P
pbrook 已提交
4457
#ifdef TARGET_SPARC64
4458
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
B
blueswir1 已提交
4459
                env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
P
pbrook 已提交
4460
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
B
blueswir1 已提交
4461 4462
                env->cansave, env->canrestore, env->otherwin, env->wstate,
                env->cleanwin, NWINDOWS - 1 - env->cwp);
P
pbrook 已提交
4463
#else
B
bellard 已提交
4464
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
B
blueswir1 已提交
4465 4466 4467 4468
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
            env->psrs?'S':'-', env->psrps?'P':'-',
            env->psret?'E':'-', env->wim);
P
pbrook 已提交
4469
#endif
B
bellard 已提交
4470
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
4471
}
B
bellard 已提交
4472

B
bellard 已提交
4473
#if defined(CONFIG_USER_ONLY)
4474
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
B
bellard 已提交
4475 4476 4477
{
    return addr;
}
B
bellard 已提交
4478

B
bellard 已提交
4479
#else
4480 4481
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
                                 int *access_index, target_ulong address, int rw,
4482
                                 int mmu_idx);
B
bellard 已提交
4483

4484
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
B
bellard 已提交
4485
{
4486
    target_phys_addr_t phys_addr;
B
bellard 已提交
4487 4488
    int prot, access_index;

4489 4490 4491 4492
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
                             MMU_KERNEL_IDX) != 0)
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
                                 0, MMU_KERNEL_IDX) != 0)
4493
            return -1;
4494 4495
    if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
        return -1;
B
bellard 已提交
4496 4497 4498 4499
    return phys_addr;
}
#endif

B
bellard 已提交
4500 4501 4502 4503 4504
void helper_flush(target_ulong addr)
{
    addr &= ~7;
    tb_invalidate_page_range(addr, addr + 8);
}