translate.c 188.8 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

   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
18
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 20 21 22 23 24 25 26 27 28
 */

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

#include "cpu.h"
#include "disas.h"
B
blueswir1 已提交
29
#include "helper.h"
B
bellard 已提交
30
#include "tcg-op.h"
31

P
pbrook 已提交
32 33 34
#define GEN_HELPER 1
#include "helper.h"

35 36
#define DEBUG_DISAS

B
bellard 已提交
37 38 39 40
#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 已提交
41
/* global register indexes */
P
pbrook 已提交
42
static TCGv_ptr cpu_env, cpu_regwptr;
43 44
static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
static TCGv_i32 cpu_cc_op;
P
pbrook 已提交
45 46
static TCGv_i32 cpu_psr;
static TCGv cpu_fsr, cpu_pc, cpu_npc, cpu_gregs[8];
47 48 49 50
static TCGv cpu_y;
#ifndef CONFIG_USER_ONLY
static TCGv cpu_tbr;
#endif
51
static TCGv cpu_cond, cpu_dst, cpu_addr, cpu_val;
52
#ifdef TARGET_SPARC64
P
pbrook 已提交
53 54
static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs;
static TCGv cpu_gsr;
55
static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
P
pbrook 已提交
56 57
static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
static TCGv_i32 cpu_softint;
58 59
#else
static TCGv cpu_wim;
60
#endif
B
blueswir1 已提交
61
/* local register indexes (only used inside old micro ops) */
P
pbrook 已提交
62 63 64
static TCGv cpu_tmp0;
static TCGv_i32 cpu_tmp32;
static TCGv_i64 cpu_tmp64;
B
blueswir1 已提交
65
/* Floating point registers */
66
static TCGv_i64 cpu_fpr[TARGET_DPREGS];
B
blueswir1 已提交
67

68 69 70
static target_ulong gen_opc_npc[OPC_BUF_SIZE];
static target_ulong gen_opc_jump_pc[2];

P
pbrook 已提交
71 72
#include "gen-icount.h"

73
typedef struct DisasContext {
B
blueswir1 已提交
74 75
    target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
    target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
B
bellard 已提交
76
    target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
77
    int is_br;
78
    int mem_idx;
B
bellard 已提交
79
    int fpu_enabled;
B
blueswir1 已提交
80
    int address_mask_32bit;
81
    int singlestep;
82
    uint32_t cc_op;  /* current CC operation */
83
    struct TranslationBlock *tb;
84
    sparc_def_t *def;
85 86
    TCGv_i32 t32[3];
    int n_t32;
87 88
} DisasContext;

B
bellard 已提交
89
// This function uses non-native bit order
B
Blue Swirl 已提交
90 91
#define GET_FIELD(X, FROM, TO)                                  \
    ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
92

B
bellard 已提交
93
// This function uses the order in the manuals, i.e. bit 0 is 2^0
B
Blue Swirl 已提交
94
#define GET_FIELD_SP(X, FROM, TO)               \
B
bellard 已提交
95 96 97
    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 已提交
98
#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
B
bellard 已提交
99 100

#ifdef TARGET_SPARC64
101
#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
B
blueswir1 已提交
102
#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
B
bellard 已提交
103
#else
104
#define DFPREG(r) (r & 0x1e)
B
blueswir1 已提交
105
#define QFPREG(r) (r & 0x1c)
B
bellard 已提交
106 107
#endif

B
blueswir1 已提交
108 109 110
#define UA2005_HTRAP_MASK 0xff
#define V8_TRAP_MASK 0x7f

B
bellard 已提交
111 112 113 114 115 116
static int sign_extend(int x, int len)
{
    len = 32 - len;
    return (x << len) >> len;
}

117 118
#define IS_IMM (insn & (1<<13))

119 120 121 122 123 124 125
static inline void gen_update_fprs_dirty(int rd)
{
#if defined(TARGET_SPARC64)
    tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2);
#endif
}

B
blueswir1 已提交
126
/* floating point registers moves */
127 128
static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
{
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
#if TCG_TARGET_REG_BITS == 32
    if (src & 1) {
        return TCGV_LOW(cpu_fpr[src / 2]);
    } else {
        return TCGV_HIGH(cpu_fpr[src / 2]);
    }
#else
    if (src & 1) {
        return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2]));
    } else {
        TCGv_i32 ret = tcg_temp_local_new_i32();
        TCGv_i64 t = tcg_temp_new_i64();

        tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32);
        tcg_gen_trunc_i64_i32(ret, t);
        tcg_temp_free_i64(t);

        dc->t32[dc->n_t32++] = ret;
        assert(dc->n_t32 <= ARRAY_SIZE(dc->t32));

        return ret;
    }
#endif
152 153 154 155
}

static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
{
156 157 158 159 160 161 162 163 164 165 166
#if TCG_TARGET_REG_BITS == 32
    if (dst & 1) {
        tcg_gen_mov_i32(TCGV_LOW(cpu_fpr[dst / 2]), v);
    } else {
        tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr[dst / 2]), v);
    }
#else
    TCGv_i64 t = MAKE_TCGV_I64(GET_TCGV_I32(v));
    tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
                        (dst & 1 ? 0 : 32), 32);
#endif
167
    gen_update_fprs_dirty(dst);
168 169 170 171 172 173 174
}

static TCGv_i32 gen_dest_fpr_F(void)
{
    return cpu_tmp32;
}

175 176 177
static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
{
    src = DFPREG(src);
178
    return cpu_fpr[src / 2];
179 180 181 182 183
}

static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
{
    dst = DFPREG(dst);
184
    tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
185 186 187 188 189 190 191 192
    gen_update_fprs_dirty(dst);
}

static TCGv_i64 gen_dest_fpr_D(void)
{
    return cpu_tmp64;
}

B
blueswir1 已提交
193 194
static void gen_op_load_fpr_QT0(unsigned int src)
{
195 196 197 198
    tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
                   offsetof(CPU_QuadU, ll.upper));
    tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
                   offsetof(CPU_QuadU, ll.lower));
B
blueswir1 已提交
199 200 201 202
}

static void gen_op_load_fpr_QT1(unsigned int src)
{
203 204 205 206
    tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt1) +
                   offsetof(CPU_QuadU, ll.upper));
    tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
                   offsetof(CPU_QuadU, ll.lower));
B
blueswir1 已提交
207 208 209 210
}

static void gen_op_store_QT0_fpr(unsigned int dst)
{
211 212 213 214
    tcg_gen_ld_i64(cpu_fpr[dst / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
                   offsetof(CPU_QuadU, ll.upper));
    tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
                   offsetof(CPU_QuadU, ll.lower));
B
blueswir1 已提交
215
}
B
blueswir1 已提交
216

217
#ifdef TARGET_SPARC64
218
static void gen_move_Q(unsigned int rd, unsigned int rs)
219 220 221 222
{
    rd = QFPREG(rd);
    rs = QFPREG(rs);

223 224
    tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
    tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
225 226 227 228
    gen_update_fprs_dirty(rd);
}
#endif

229 230
/* moves */
#ifdef CONFIG_USER_ONLY
B
bellard 已提交
231
#define supervisor(dc) 0
232
#ifdef TARGET_SPARC64
B
blueswir1 已提交
233
#define hypervisor(dc) 0
234
#endif
B
bellard 已提交
235
#else
236
#define supervisor(dc) (dc->mem_idx >= MMU_KERNEL_IDX)
237
#ifdef TARGET_SPARC64
238
#define hypervisor(dc) (dc->mem_idx == MMU_HYPV_IDX)
B
blueswir1 已提交
239
#else
B
bellard 已提交
240
#endif
241 242
#endif

B
blueswir1 已提交
243 244 245
#ifdef TARGET_SPARC64
#ifndef TARGET_ABI32
#define AM_CHECK(dc) ((dc)->address_mask_32bit)
B
blueswir1 已提交
246
#else
B
blueswir1 已提交
247 248
#define AM_CHECK(dc) (1)
#endif
B
blueswir1 已提交
249
#endif
250

B
blueswir1 已提交
251 252 253 254 255 256 257 258
static inline void gen_address_mask(DisasContext *dc, TCGv addr)
{
#ifdef TARGET_SPARC64
    if (AM_CHECK(dc))
        tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
#endif
}

B
blueswir1 已提交
259
static inline void gen_movl_reg_TN(int reg, TCGv tn)
260
{
B
blueswir1 已提交
261 262 263
    if (reg == 0)
        tcg_gen_movi_tl(tn, 0);
    else if (reg < 8)
B
blueswir1 已提交
264
        tcg_gen_mov_tl(tn, cpu_gregs[reg]);
B
blueswir1 已提交
265 266
    else {
        tcg_gen_ld_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
267 268 269
    }
}

B
blueswir1 已提交
270
static inline void gen_movl_TN_reg(int reg, TCGv tn)
271
{
B
blueswir1 已提交
272 273 274
    if (reg == 0)
        return;
    else if (reg < 8)
B
blueswir1 已提交
275
        tcg_gen_mov_tl(cpu_gregs[reg], tn);
B
blueswir1 已提交
276 277
    else {
        tcg_gen_st_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
278 279 280
    }
}

281
static inline void gen_goto_tb(DisasContext *s, int tb_num,
282 283 284 285 286 287
                               target_ulong pc, target_ulong npc)
{
    TranslationBlock *tb;

    tb = s->tb;
    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
288 289
        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
        !s->singlestep)  {
290
        /* jump to same page: we can use a direct jump */
B
bellard 已提交
291
        tcg_gen_goto_tb(tb_num);
B
blueswir1 已提交
292 293
        tcg_gen_movi_tl(cpu_pc, pc);
        tcg_gen_movi_tl(cpu_npc, npc);
294
        tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
295 296
    } else {
        /* jump to another page: currently not optimized */
B
blueswir1 已提交
297 298
        tcg_gen_movi_tl(cpu_pc, pc);
        tcg_gen_movi_tl(cpu_npc, npc);
B
bellard 已提交
299
        tcg_gen_exit_tb(0);
300 301 302
    }
}

303
// XXX suboptimal
P
pbrook 已提交
304
static inline void gen_mov_reg_N(TCGv reg, TCGv_i32 src)
305
{
B
blueswir1 已提交
306
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
307
    tcg_gen_shri_tl(reg, reg, PSR_NEG_SHIFT);
308 309 310
    tcg_gen_andi_tl(reg, reg, 0x1);
}

P
pbrook 已提交
311
static inline void gen_mov_reg_Z(TCGv reg, TCGv_i32 src)
312
{
B
blueswir1 已提交
313
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
314
    tcg_gen_shri_tl(reg, reg, PSR_ZERO_SHIFT);
315 316 317
    tcg_gen_andi_tl(reg, reg, 0x1);
}

P
pbrook 已提交
318
static inline void gen_mov_reg_V(TCGv reg, TCGv_i32 src)
319
{
B
blueswir1 已提交
320
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
321
    tcg_gen_shri_tl(reg, reg, PSR_OVF_SHIFT);
322 323 324
    tcg_gen_andi_tl(reg, reg, 0x1);
}

P
pbrook 已提交
325
static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src)
326
{
B
blueswir1 已提交
327
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
328
    tcg_gen_shri_tl(reg, reg, PSR_CARRY_SHIFT);
329 330 331
    tcg_gen_andi_tl(reg, reg, 0x1);
}

332 333
static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
{
P
pbrook 已提交
334 335
    TCGv r_temp;
    TCGv_i32 r_const;
336 337 338 339
    int l1;

    l1 = gen_new_label();

P
pbrook 已提交
340
    r_temp = tcg_temp_new();
341
    tcg_gen_xor_tl(r_temp, src1, src2);
B
blueswir1 已提交
342
    tcg_gen_not_tl(r_temp, r_temp);
343 344
    tcg_gen_xor_tl(cpu_tmp0, src1, dst);
    tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
345
    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
P
pbrook 已提交
346
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
B
blueswir1 已提交
347
    r_const = tcg_const_i32(TT_TOVF);
348
    gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
349
    tcg_temp_free_i32(r_const);
350
    gen_set_label(l1);
B
blueswir1 已提交
351
    tcg_temp_free(r_temp);
352 353 354 355 356
}

static inline void gen_tag_tv(TCGv src1, TCGv src2)
{
    int l1;
P
pbrook 已提交
357
    TCGv_i32 r_const;
358 359

    l1 = gen_new_label();
360 361
    tcg_gen_or_tl(cpu_tmp0, src1, src2);
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
P
pbrook 已提交
362
    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
B
blueswir1 已提交
363
    r_const = tcg_const_i32(TT_TOVF);
364
    gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
365
    tcg_temp_free_i32(r_const);
366 367 368
    gen_set_label(l1);
}

369 370 371 372 373
static inline void gen_op_addi_cc(TCGv dst, TCGv src1, target_long src2)
{
    tcg_gen_mov_tl(cpu_cc_src, src1);
    tcg_gen_movi_tl(cpu_cc_src2, src2);
    tcg_gen_addi_tl(cpu_cc_dst, cpu_cc_src, src2);
B
Blue Swirl 已提交
374
    tcg_gen_mov_tl(dst, cpu_cc_dst);
375 376
}

377
static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
378
{
379
    tcg_gen_mov_tl(cpu_cc_src, src1);
380
    tcg_gen_mov_tl(cpu_cc_src2, src2);
381
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
B
Blue Swirl 已提交
382
    tcg_gen_mov_tl(dst, cpu_cc_dst);
383 384
}

385
static TCGv_i32 gen_add32_carry32(void)
386
{
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
    TCGv_i32 carry_32, cc_src1_32, cc_src2_32;

    /* Carry is computed from a previous add: (dst < src)  */
#if TARGET_LONG_BITS == 64
    cc_src1_32 = tcg_temp_new_i32();
    cc_src2_32 = tcg_temp_new_i32();
    tcg_gen_trunc_i64_i32(cc_src1_32, cpu_cc_dst);
    tcg_gen_trunc_i64_i32(cc_src2_32, cpu_cc_src);
#else
    cc_src1_32 = cpu_cc_dst;
    cc_src2_32 = cpu_cc_src;
#endif

    carry_32 = tcg_temp_new_i32();
    tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);

#if TARGET_LONG_BITS == 64
    tcg_temp_free_i32(cc_src1_32);
    tcg_temp_free_i32(cc_src2_32);
#endif

    return carry_32;
409 410
}

411
static TCGv_i32 gen_sub32_carry32(void)
412
{
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
    TCGv_i32 carry_32, cc_src1_32, cc_src2_32;

    /* Carry is computed from a previous borrow: (src1 < src2)  */
#if TARGET_LONG_BITS == 64
    cc_src1_32 = tcg_temp_new_i32();
    cc_src2_32 = tcg_temp_new_i32();
    tcg_gen_trunc_i64_i32(cc_src1_32, cpu_cc_src);
    tcg_gen_trunc_i64_i32(cc_src2_32, cpu_cc_src2);
#else
    cc_src1_32 = cpu_cc_src;
    cc_src2_32 = cpu_cc_src2;
#endif

    carry_32 = tcg_temp_new_i32();
    tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);

#if TARGET_LONG_BITS == 64
    tcg_temp_free_i32(cc_src1_32);
    tcg_temp_free_i32(cc_src2_32);
#endif

    return carry_32;
}

static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
                            TCGv src2, int update_cc)
{
    TCGv_i32 carry_32;
    TCGv carry;

    switch (dc->cc_op) {
    case CC_OP_DIV:
    case CC_OP_LOGIC:
        /* Carry is known to be zero.  Fall back to plain ADD.  */
        if (update_cc) {
            gen_op_add_cc(dst, src1, src2);
        } else {
            tcg_gen_add_tl(dst, src1, src2);
        }
        return;

    case CC_OP_ADD:
    case CC_OP_TADD:
    case CC_OP_TADDTV:
#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
        {
            /* For 32-bit hosts, we can re-use the host's hardware carry
               generation by using an ADD2 opcode.  We discard the low
               part of the output.  Ideally we'd combine this operation
               with the add that generated the carry in the first place.  */
            TCGv dst_low = tcg_temp_new();
            tcg_gen_op6_i32(INDEX_op_add2_i32, dst_low, dst,
                            cpu_cc_src, src1, cpu_cc_src2, src2);
            tcg_temp_free(dst_low);
            goto add_done;
        }
#endif
        carry_32 = gen_add32_carry32();
        break;

    case CC_OP_SUB:
    case CC_OP_TSUB:
    case CC_OP_TSUBTV:
        carry_32 = gen_sub32_carry32();
        break;

    default:
        /* We need external help to produce the carry.  */
        carry_32 = tcg_temp_new_i32();
482
        gen_helper_compute_C_icc(carry_32, cpu_env);
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
        break;
    }

#if TARGET_LONG_BITS == 64
    carry = tcg_temp_new();
    tcg_gen_extu_i32_i64(carry, carry_32);
#else
    carry = carry_32;
#endif

    tcg_gen_add_tl(dst, src1, src2);
    tcg_gen_add_tl(dst, dst, carry);

    tcg_temp_free_i32(carry_32);
#if TARGET_LONG_BITS == 64
    tcg_temp_free(carry);
#endif

#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
 add_done:
#endif
    if (update_cc) {
        tcg_gen_mov_tl(cpu_cc_src, src1);
        tcg_gen_mov_tl(cpu_cc_src2, src2);
        tcg_gen_mov_tl(cpu_cc_dst, dst);
        tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
        dc->cc_op = CC_OP_ADDX;
    }
511 512
}

513
static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
514
{
515
    tcg_gen_mov_tl(cpu_cc_src, src1);
516
    tcg_gen_mov_tl(cpu_cc_src2, src2);
517 518
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    tcg_gen_mov_tl(dst, cpu_cc_dst);
519 520
}

521
static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
522
{
523
    tcg_gen_mov_tl(cpu_cc_src, src1);
524 525
    tcg_gen_mov_tl(cpu_cc_src2, src2);
    gen_tag_tv(cpu_cc_src, cpu_cc_src2);
526 527 528
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    gen_add_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    tcg_gen_mov_tl(dst, cpu_cc_dst);
529 530 531 532
}

static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
{
P
pbrook 已提交
533 534
    TCGv r_temp;
    TCGv_i32 r_const;
535 536 537 538
    int l1;

    l1 = gen_new_label();

P
pbrook 已提交
539
    r_temp = tcg_temp_new();
540
    tcg_gen_xor_tl(r_temp, src1, src2);
541 542
    tcg_gen_xor_tl(cpu_tmp0, src1, dst);
    tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
543
    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
P
pbrook 已提交
544
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
B
blueswir1 已提交
545
    r_const = tcg_const_i32(TT_TOVF);
546
    gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
547
    tcg_temp_free_i32(r_const);
548
    gen_set_label(l1);
B
blueswir1 已提交
549
    tcg_temp_free(r_temp);
550 551
}

B
Blue Swirl 已提交
552
static inline void gen_op_subi_cc(TCGv dst, TCGv src1, target_long src2, DisasContext *dc)
553 554 555
{
    tcg_gen_mov_tl(cpu_cc_src, src1);
    tcg_gen_movi_tl(cpu_cc_src2, src2);
B
Blue Swirl 已提交
556
    if (src2 == 0) {
B
Blue Swirl 已提交
557 558 559
        tcg_gen_mov_tl(cpu_cc_dst, src1);
        tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
        dc->cc_op = CC_OP_LOGIC;
B
Blue Swirl 已提交
560 561
    } else {
        tcg_gen_subi_tl(cpu_cc_dst, cpu_cc_src, src2);
B
Blue Swirl 已提交
562 563
        tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
        dc->cc_op = CC_OP_SUB;
B
Blue Swirl 已提交
564
    }
B
Blue Swirl 已提交
565
    tcg_gen_mov_tl(dst, cpu_cc_dst);
566 567 568
}

static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
569
{
570
    tcg_gen_mov_tl(cpu_cc_src, src1);
571
    tcg_gen_mov_tl(cpu_cc_src2, src2);
572
    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
B
Blue Swirl 已提交
573
    tcg_gen_mov_tl(dst, cpu_cc_dst);
574 575
}

576 577
static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
                            TCGv src2, int update_cc)
578
{
579 580
    TCGv_i32 carry_32;
    TCGv carry;
581

582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
    switch (dc->cc_op) {
    case CC_OP_DIV:
    case CC_OP_LOGIC:
        /* Carry is known to be zero.  Fall back to plain SUB.  */
        if (update_cc) {
            gen_op_sub_cc(dst, src1, src2);
        } else {
            tcg_gen_sub_tl(dst, src1, src2);
        }
        return;

    case CC_OP_ADD:
    case CC_OP_TADD:
    case CC_OP_TADDTV:
        carry_32 = gen_add32_carry32();
        break;

    case CC_OP_SUB:
    case CC_OP_TSUB:
    case CC_OP_TSUBTV:
#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
        {
            /* For 32-bit hosts, we can re-use the host's hardware carry
               generation by using a SUB2 opcode.  We discard the low
               part of the output.  Ideally we'd combine this operation
               with the add that generated the carry in the first place.  */
            TCGv dst_low = tcg_temp_new();
            tcg_gen_op6_i32(INDEX_op_sub2_i32, dst_low, dst,
                            cpu_cc_src, src1, cpu_cc_src2, src2);
            tcg_temp_free(dst_low);
            goto sub_done;
        }
#endif
        carry_32 = gen_sub32_carry32();
        break;

    default:
        /* We need external help to produce the carry.  */
        carry_32 = tcg_temp_new_i32();
621
        gen_helper_compute_C_icc(carry_32, cpu_env);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
        break;
    }

#if TARGET_LONG_BITS == 64
    carry = tcg_temp_new();
    tcg_gen_extu_i32_i64(carry, carry_32);
#else
    carry = carry_32;
#endif

    tcg_gen_sub_tl(dst, src1, src2);
    tcg_gen_sub_tl(dst, dst, carry);

    tcg_temp_free_i32(carry_32);
#if TARGET_LONG_BITS == 64
    tcg_temp_free(carry);
#endif

#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
 sub_done:
#endif
    if (update_cc) {
        tcg_gen_mov_tl(cpu_cc_src, src1);
        tcg_gen_mov_tl(cpu_cc_src2, src2);
        tcg_gen_mov_tl(cpu_cc_dst, dst);
        tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
        dc->cc_op = CC_OP_SUBX;
    }
650 651
}

652
static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
653
{
654
    tcg_gen_mov_tl(cpu_cc_src, src1);
655
    tcg_gen_mov_tl(cpu_cc_src2, src2);
656 657
    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    tcg_gen_mov_tl(dst, cpu_cc_dst);
658 659
}

660
static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
661
{
662
    tcg_gen_mov_tl(cpu_cc_src, src1);
663 664
    tcg_gen_mov_tl(cpu_cc_src2, src2);
    gen_tag_tv(cpu_cc_src, cpu_cc_src2);
665 666 667
    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    gen_sub_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    tcg_gen_mov_tl(dst, cpu_cc_dst);
668 669
}

670
static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
671
{
B
blueswir1 已提交
672
    TCGv r_temp;
673
    int l1;
B
blueswir1 已提交
674 675

    l1 = gen_new_label();
P
pbrook 已提交
676
    r_temp = tcg_temp_new();
B
blueswir1 已提交
677 678 679 680 681

    /* old op:
    if (!(env->y & 1))
        T1 = 0;
    */
682
    tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
683
    tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
684
    tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
B
blueswir1 已提交
685
    tcg_gen_brcondi_tl(TCG_COND_NE, r_temp, 0, l1);
B
blueswir1 已提交
686
    tcg_gen_movi_tl(cpu_cc_src2, 0);
687
    gen_set_label(l1);
B
blueswir1 已提交
688 689 690

    // b2 = T0 & 1;
    // env->y = (b2 << 31) | (env->y >> 1);
B
blueswir1 已提交
691 692
    tcg_gen_andi_tl(r_temp, cpu_cc_src, 0x1);
    tcg_gen_shli_tl(r_temp, r_temp, 31);
693
    tcg_gen_shri_tl(cpu_tmp0, cpu_y, 1);
694
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x7fffffff);
695 696
    tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, r_temp);
    tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
B
blueswir1 已提交
697 698 699 700 701

    // b1 = N ^ V;
    gen_mov_reg_N(cpu_tmp0, cpu_psr);
    gen_mov_reg_V(r_temp, cpu_psr);
    tcg_gen_xor_tl(cpu_tmp0, cpu_tmp0, r_temp);
B
blueswir1 已提交
702
    tcg_temp_free(r_temp);
B
blueswir1 已提交
703 704 705 706

    // T0 = (b1 << 31) | (T0 >> 1);
    // src1 = T0;
    tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, 31);
707
    tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1);
B
blueswir1 已提交
708 709
    tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);

710
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
B
blueswir1 已提交
711

712
    tcg_gen_mov_tl(dst, cpu_cc_dst);
B
blueswir1 已提交
713 714
}

715
static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
B
blueswir1 已提交
716
{
717
    TCGv_i32 r_src1, r_src2;
P
pbrook 已提交
718
    TCGv_i64 r_temp, r_temp2;
B
blueswir1 已提交
719

720 721 722 723 724 725
    r_src1 = tcg_temp_new_i32();
    r_src2 = tcg_temp_new_i32();

    tcg_gen_trunc_tl_i32(r_src1, src1);
    tcg_gen_trunc_tl_i32(r_src2, src2);

P
pbrook 已提交
726 727
    r_temp = tcg_temp_new_i64();
    r_temp2 = tcg_temp_new_i64();
B
blueswir1 已提交
728

729 730 731 732 733 734 735 736
    if (sign_ext) {
        tcg_gen_ext_i32_i64(r_temp, r_src2);
        tcg_gen_ext_i32_i64(r_temp2, r_src1);
    } else {
        tcg_gen_extu_i32_i64(r_temp, r_src2);
        tcg_gen_extu_i32_i64(r_temp2, r_src1);
    }

B
blueswir1 已提交
737 738 739
    tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);

    tcg_gen_shri_i64(r_temp, r_temp2, 32);
B
blueswir1 已提交
740
    tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
P
pbrook 已提交
741
    tcg_temp_free_i64(r_temp);
742
    tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
743

744
    tcg_gen_trunc_i64_tl(dst, r_temp2);
745

P
pbrook 已提交
746
    tcg_temp_free_i64(r_temp2);
747 748 749

    tcg_temp_free_i32(r_src1);
    tcg_temp_free_i32(r_src2);
B
blueswir1 已提交
750 751
}

752
static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
753
{
754 755 756
    /* zero-extend truncated operands before multiplication */
    gen_op_multiply(dst, src1, src2, 0);
}
B
blueswir1 已提交
757

758 759 760 761
static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
{
    /* sign-extend truncated operands before multiplication */
    gen_op_multiply(dst, src1, src2, 1);
B
blueswir1 已提交
762 763
}

B
blueswir1 已提交
764
#ifdef TARGET_SPARC64
B
blueswir1 已提交
765
static inline void gen_trap_ifdivzero_tl(TCGv divisor)
B
blueswir1 已提交
766
{
P
pbrook 已提交
767
    TCGv_i32 r_const;
B
blueswir1 已提交
768 769 770
    int l1;

    l1 = gen_new_label();
P
pbrook 已提交
771
    tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
B
blueswir1 已提交
772
    r_const = tcg_const_i32(TT_DIV_ZERO);
773
    gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
774
    tcg_temp_free_i32(r_const);
B
blueswir1 已提交
775 776 777
    gen_set_label(l1);
}

778
static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
779 780
{
    int l1, l2;
781
    TCGv r_temp1, r_temp2;
B
blueswir1 已提交
782 783 784

    l1 = gen_new_label();
    l2 = gen_new_label();
785 786 787 788 789 790 791
    r_temp1 = tcg_temp_local_new();
    r_temp2 = tcg_temp_local_new();
    tcg_gen_mov_tl(r_temp1, src1);
    tcg_gen_mov_tl(r_temp2, src2);
    gen_trap_ifdivzero_tl(r_temp2);
    tcg_gen_brcondi_tl(TCG_COND_NE, r_temp1, INT64_MIN, l1);
    tcg_gen_brcondi_tl(TCG_COND_NE, r_temp2, -1, l1);
792
    tcg_gen_movi_i64(dst, INT64_MIN);
B
blueswir1 已提交
793
    tcg_gen_br(l2);
B
blueswir1 已提交
794
    gen_set_label(l1);
795
    tcg_gen_div_i64(dst, r_temp1, r_temp2);
B
blueswir1 已提交
796
    gen_set_label(l2);
797 798
    tcg_temp_free(r_temp1);
    tcg_temp_free(r_temp2);
B
blueswir1 已提交
799 800 801
}
#endif

802 803 804 805 806 807 808
// 1
static inline void gen_op_eval_ba(TCGv dst)
{
    tcg_gen_movi_tl(dst, 1);
}

// Z
P
pbrook 已提交
809
static inline void gen_op_eval_be(TCGv dst, TCGv_i32 src)
810 811 812 813 814
{
    gen_mov_reg_Z(dst, src);
}

// Z | (N ^ V)
P
pbrook 已提交
815
static inline void gen_op_eval_ble(TCGv dst, TCGv_i32 src)
816
{
817
    gen_mov_reg_N(cpu_tmp0, src);
818
    gen_mov_reg_V(dst, src);
819 820 821
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
    gen_mov_reg_Z(cpu_tmp0, src);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
822 823 824
}

// N ^ V
P
pbrook 已提交
825
static inline void gen_op_eval_bl(TCGv dst, TCGv_i32 src)
826
{
827
    gen_mov_reg_V(cpu_tmp0, src);
828
    gen_mov_reg_N(dst, src);
829
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
830 831 832
}

// C | Z
P
pbrook 已提交
833
static inline void gen_op_eval_bleu(TCGv dst, TCGv_i32 src)
834
{
835
    gen_mov_reg_Z(cpu_tmp0, src);
836
    gen_mov_reg_C(dst, src);
837
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
838 839 840
}

// C
P
pbrook 已提交
841
static inline void gen_op_eval_bcs(TCGv dst, TCGv_i32 src)
842 843 844 845 846
{
    gen_mov_reg_C(dst, src);
}

// V
P
pbrook 已提交
847
static inline void gen_op_eval_bvs(TCGv dst, TCGv_i32 src)
848 849 850 851 852 853 854 855 856 857 858
{
    gen_mov_reg_V(dst, src);
}

// 0
static inline void gen_op_eval_bn(TCGv dst)
{
    tcg_gen_movi_tl(dst, 0);
}

// N
P
pbrook 已提交
859
static inline void gen_op_eval_bneg(TCGv dst, TCGv_i32 src)
860 861 862 863 864
{
    gen_mov_reg_N(dst, src);
}

// !Z
P
pbrook 已提交
865
static inline void gen_op_eval_bne(TCGv dst, TCGv_i32 src)
866 867 868 869 870 871
{
    gen_mov_reg_Z(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !(Z | (N ^ V))
P
pbrook 已提交
872
static inline void gen_op_eval_bg(TCGv dst, TCGv_i32 src)
873
{
874
    gen_mov_reg_N(cpu_tmp0, src);
875
    gen_mov_reg_V(dst, src);
876 877 878
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
    gen_mov_reg_Z(cpu_tmp0, src);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
879 880 881 882
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !(N ^ V)
P
pbrook 已提交
883
static inline void gen_op_eval_bge(TCGv dst, TCGv_i32 src)
884
{
885
    gen_mov_reg_V(cpu_tmp0, src);
886
    gen_mov_reg_N(dst, src);
887
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
888 889 890 891
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !(C | Z)
P
pbrook 已提交
892
static inline void gen_op_eval_bgu(TCGv dst, TCGv_i32 src)
893
{
894
    gen_mov_reg_Z(cpu_tmp0, src);
895
    gen_mov_reg_C(dst, src);
896
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
897 898 899 900
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !C
P
pbrook 已提交
901
static inline void gen_op_eval_bcc(TCGv dst, TCGv_i32 src)
902 903 904 905 906 907
{
    gen_mov_reg_C(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !N
P
pbrook 已提交
908
static inline void gen_op_eval_bpos(TCGv dst, TCGv_i32 src)
909 910 911 912 913 914
{
    gen_mov_reg_N(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !V
P
pbrook 已提交
915
static inline void gen_op_eval_bvc(TCGv dst, TCGv_i32 src)
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
{
    gen_mov_reg_V(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

/*
  FPSR bit field FCC1 | FCC0:
   0 =
   1 <
   2 >
   3 unordered
*/
static inline void gen_mov_reg_FCC0(TCGv reg, TCGv src,
                                    unsigned int fcc_offset)
{
931
    tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset);
932 933 934 935 936 937
    tcg_gen_andi_tl(reg, reg, 0x1);
}

static inline void gen_mov_reg_FCC1(TCGv reg, TCGv src,
                                    unsigned int fcc_offset)
{
938
    tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset);
939 940 941 942 943 944 945 946
    tcg_gen_andi_tl(reg, reg, 0x1);
}

// !0: FCC0 | FCC1
static inline void gen_op_eval_fbne(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
947 948
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
949 950 951 952 953 954 955
}

// 1 or 2: FCC0 ^ FCC1
static inline void gen_op_eval_fblg(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
956 957
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
958 959 960 961 962 963 964 965 966 967 968 969 970 971
}

// 1 or 3: FCC0
static inline void gen_op_eval_fbul(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
}

// 1: FCC0 & !FCC1
static inline void gen_op_eval_fbl(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
972 973 974
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_xori_tl(cpu_tmp0, cpu_tmp0, 0x1);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
}

// 2 or 3: FCC1
static inline void gen_op_eval_fbug(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC1(dst, src, fcc_offset);
}

// 2: !FCC0 & FCC1
static inline void gen_op_eval_fbg(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
    tcg_gen_xori_tl(dst, dst, 0x1);
990 991
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
992 993 994 995 996 997 998
}

// 3: FCC0 & FCC1
static inline void gen_op_eval_fbu(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
999 1000
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
1001 1002 1003 1004 1005 1006 1007
}

// 0: !(FCC0 | FCC1)
static inline void gen_op_eval_fbe(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
1008 1009
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
1010 1011 1012 1013 1014 1015 1016 1017
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// 0 or 3: !(FCC0 ^ FCC1)
static inline void gen_op_eval_fbue(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
1018 1019
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// 0 or 2: !FCC0
static inline void gen_op_eval_fbge(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !1: !(FCC0 & !FCC1)
static inline void gen_op_eval_fbuge(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
1036 1037 1038
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_xori_tl(cpu_tmp0, cpu_tmp0, 0x1);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// 0 or 1: !FCC1
static inline void gen_op_eval_fble(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC1(dst, src, fcc_offset);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !2: !(!FCC0 & FCC1)
static inline void gen_op_eval_fbule(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
    tcg_gen_xori_tl(dst, dst, 0x1);
1056 1057
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
1058 1059 1060 1061 1062 1063 1064 1065
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !3: !(FCC0 & FCC1)
static inline void gen_op_eval_fbo(TCGv dst, TCGv src,
                                    unsigned int fcc_offset)
{
    gen_mov_reg_FCC0(dst, src, fcc_offset);
1066 1067
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
1068 1069 1070
    tcg_gen_xori_tl(dst, dst, 0x1);
}

B
blueswir1 已提交
1071
static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
1072
                               target_ulong pc2, TCGv r_cond)
B
bellard 已提交
1073 1074 1075 1076 1077
{
    int l1;

    l1 = gen_new_label();

P
pbrook 已提交
1078
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
B
bellard 已提交
1079

1080
    gen_goto_tb(dc, 0, pc1, pc1 + 4);
B
bellard 已提交
1081 1082

    gen_set_label(l1);
1083
    gen_goto_tb(dc, 1, pc2, pc2 + 4);
B
bellard 已提交
1084 1085
}

B
blueswir1 已提交
1086
static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
1087
                                target_ulong pc2, TCGv r_cond)
B
bellard 已提交
1088 1089 1090 1091 1092
{
    int l1;

    l1 = gen_new_label();

P
pbrook 已提交
1093
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
B
bellard 已提交
1094

1095
    gen_goto_tb(dc, 0, pc2, pc1);
B
bellard 已提交
1096 1097

    gen_set_label(l1);
1098
    gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
B
bellard 已提交
1099 1100
}

1101 1102
static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2,
                                      TCGv r_cond)
B
bellard 已提交
1103 1104 1105 1106 1107
{
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
1108

P
pbrook 已提交
1109
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
B
bellard 已提交
1110

B
blueswir1 已提交
1111
    tcg_gen_movi_tl(cpu_npc, npc1);
B
blueswir1 已提交
1112
    tcg_gen_br(l2);
B
bellard 已提交
1113 1114

    gen_set_label(l1);
B
blueswir1 已提交
1115
    tcg_gen_movi_tl(cpu_npc, npc2);
B
bellard 已提交
1116 1117 1118
    gen_set_label(l2);
}

1119 1120 1121
/* call this function before using the condition register as it may
   have been set for a jump */
static inline void flush_cond(DisasContext *dc, TCGv cond)
B
bellard 已提交
1122 1123
{
    if (dc->npc == JUMP_PC) {
1124
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
B
bellard 已提交
1125 1126 1127 1128
        dc->npc = DYNAMIC_PC;
    }
}

1129
static inline void save_npc(DisasContext *dc, TCGv cond)
B
bellard 已提交
1130 1131
{
    if (dc->npc == JUMP_PC) {
1132
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
B
bellard 已提交
1133 1134
        dc->npc = DYNAMIC_PC;
    } else if (dc->npc != DYNAMIC_PC) {
B
blueswir1 已提交
1135
        tcg_gen_movi_tl(cpu_npc, dc->npc);
B
bellard 已提交
1136 1137 1138
    }
}

1139
static inline void save_state(DisasContext *dc, TCGv cond)
B
bellard 已提交
1140
{
B
blueswir1 已提交
1141
    tcg_gen_movi_tl(cpu_pc, dc->pc);
1142 1143 1144
    /* flush pending conditional evaluations before exposing cpu state */
    if (dc->cc_op != CC_OP_FLAGS) {
        dc->cc_op = CC_OP_FLAGS;
1145
        gen_helper_compute_psr(cpu_env);
1146
    }
1147
    save_npc(dc, cond);
B
bellard 已提交
1148 1149
}

1150
static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond)
B
bellard 已提交
1151 1152
{
    if (dc->npc == JUMP_PC) {
1153
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
B
blueswir1 已提交
1154
        tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
bellard 已提交
1155 1156
        dc->pc = DYNAMIC_PC;
    } else if (dc->npc == DYNAMIC_PC) {
B
blueswir1 已提交
1157
        tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
bellard 已提交
1158 1159 1160 1161 1162 1163
        dc->pc = DYNAMIC_PC;
    } else {
        dc->pc = dc->npc;
    }
}

1164 1165
static inline void gen_op_next_insn(void)
{
B
blueswir1 已提交
1166 1167
    tcg_gen_mov_tl(cpu_pc, cpu_npc);
    tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
1168 1169
}

1170 1171
static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
                            DisasContext *dc)
1172
{
P
pbrook 已提交
1173
    TCGv_i32 r_src;
B
bellard 已提交
1174 1175

#ifdef TARGET_SPARC64
1176
    if (cc)
1177
        r_src = cpu_xcc;
1178
    else
1179
        r_src = cpu_psr;
B
bellard 已提交
1180
#else
1181
    r_src = cpu_psr;
B
bellard 已提交
1182
#endif
1183 1184 1185 1186
    switch (dc->cc_op) {
    case CC_OP_FLAGS:
        break;
    default:
1187
        gen_helper_compute_psr(cpu_env);
1188 1189 1190
        dc->cc_op = CC_OP_FLAGS;
        break;
    }
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
    switch (cond) {
    case 0x0:
        gen_op_eval_bn(r_dst);
        break;
    case 0x1:
        gen_op_eval_be(r_dst, r_src);
        break;
    case 0x2:
        gen_op_eval_ble(r_dst, r_src);
        break;
    case 0x3:
        gen_op_eval_bl(r_dst, r_src);
        break;
    case 0x4:
        gen_op_eval_bleu(r_dst, r_src);
        break;
    case 0x5:
        gen_op_eval_bcs(r_dst, r_src);
        break;
    case 0x6:
        gen_op_eval_bneg(r_dst, r_src);
        break;
    case 0x7:
        gen_op_eval_bvs(r_dst, r_src);
        break;
    case 0x8:
        gen_op_eval_ba(r_dst);
        break;
    case 0x9:
        gen_op_eval_bne(r_dst, r_src);
        break;
    case 0xa:
        gen_op_eval_bg(r_dst, r_src);
        break;
    case 0xb:
        gen_op_eval_bge(r_dst, r_src);
        break;
    case 0xc:
        gen_op_eval_bgu(r_dst, r_src);
        break;
    case 0xd:
        gen_op_eval_bcc(r_dst, r_src);
        break;
    case 0xe:
        gen_op_eval_bpos(r_dst, r_src);
        break;
    case 0xf:
        gen_op_eval_bvc(r_dst, r_src);
        break;
    }
}
1242

1243
static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
1244
{
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
    unsigned int offset;

    switch (cc) {
    default:
    case 0x0:
        offset = 0;
        break;
    case 0x1:
        offset = 32 - 10;
        break;
    case 0x2:
        offset = 34 - 10;
        break;
    case 0x3:
        offset = 36 - 10;
        break;
    }

    switch (cond) {
    case 0x0:
        gen_op_eval_bn(r_dst);
        break;
    case 0x1:
B
blueswir1 已提交
1268
        gen_op_eval_fbne(r_dst, cpu_fsr, offset);
1269 1270
        break;
    case 0x2:
B
blueswir1 已提交
1271
        gen_op_eval_fblg(r_dst, cpu_fsr, offset);
1272 1273
        break;
    case 0x3:
B
blueswir1 已提交
1274
        gen_op_eval_fbul(r_dst, cpu_fsr, offset);
1275 1276
        break;
    case 0x4:
B
blueswir1 已提交
1277
        gen_op_eval_fbl(r_dst, cpu_fsr, offset);
1278 1279
        break;
    case 0x5:
B
blueswir1 已提交
1280
        gen_op_eval_fbug(r_dst, cpu_fsr, offset);
1281 1282
        break;
    case 0x6:
B
blueswir1 已提交
1283
        gen_op_eval_fbg(r_dst, cpu_fsr, offset);
1284 1285
        break;
    case 0x7:
B
blueswir1 已提交
1286
        gen_op_eval_fbu(r_dst, cpu_fsr, offset);
1287 1288 1289 1290 1291
        break;
    case 0x8:
        gen_op_eval_ba(r_dst);
        break;
    case 0x9:
B
blueswir1 已提交
1292
        gen_op_eval_fbe(r_dst, cpu_fsr, offset);
1293 1294
        break;
    case 0xa:
B
blueswir1 已提交
1295
        gen_op_eval_fbue(r_dst, cpu_fsr, offset);
1296 1297
        break;
    case 0xb:
B
blueswir1 已提交
1298
        gen_op_eval_fbge(r_dst, cpu_fsr, offset);
1299 1300
        break;
    case 0xc:
B
blueswir1 已提交
1301
        gen_op_eval_fbuge(r_dst, cpu_fsr, offset);
1302 1303
        break;
    case 0xd:
B
blueswir1 已提交
1304
        gen_op_eval_fble(r_dst, cpu_fsr, offset);
1305 1306
        break;
    case 0xe:
B
blueswir1 已提交
1307
        gen_op_eval_fbule(r_dst, cpu_fsr, offset);
1308 1309
        break;
    case 0xf:
B
blueswir1 已提交
1310
        gen_op_eval_fbo(r_dst, cpu_fsr, offset);
1311 1312
        break;
    }
1313
}
1314

1315
#ifdef TARGET_SPARC64
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
// 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,
};
1327

1328
static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
1329 1330 1331 1332
{
    int l1;

    l1 = gen_new_label();
1333
    tcg_gen_movi_tl(r_dst, 0);
P
pbrook 已提交
1334
    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], r_src, 0, l1);
1335 1336 1337
    tcg_gen_movi_tl(r_dst, 1);
    gen_set_label(l1);
}
B
bellard 已提交
1338
#endif
1339

1340 1341
static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
                      TCGv r_cond)
1342
{
1343
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1344
    target_ulong target = dc->pc + offset;
1345

1346
    if (cond == 0x0) {
B
blueswir1 已提交
1347 1348 1349 1350 1351 1352 1353 1354
        /* 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;
        }
1355
    } else if (cond == 0x8) {
B
blueswir1 已提交
1356 1357 1358 1359 1360 1361 1362
        /* unconditional taken */
        if (a) {
            dc->pc = target;
            dc->npc = dc->pc + 4;
        } else {
            dc->pc = dc->npc;
            dc->npc = target;
1363
            tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
blueswir1 已提交
1364
        }
1365
    } else {
1366
        flush_cond(dc, r_cond);
1367
        gen_cond(r_cond, cc, cond, dc);
B
blueswir1 已提交
1368
        if (a) {
1369
            gen_branch_a(dc, target, dc->npc, r_cond);
1370
            dc->is_br = 1;
B
blueswir1 已提交
1371
        } else {
1372
            dc->pc = dc->npc;
B
bellard 已提交
1373
            dc->jump_pc[0] = target;
1374 1375 1376 1377 1378 1379 1380
            if (unlikely(dc->npc == DYNAMIC_PC)) {
                dc->jump_pc[1] = DYNAMIC_PC;
                tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
            } else {
                dc->jump_pc[1] = dc->npc + 4;
                dc->npc = JUMP_PC;
            }
B
blueswir1 已提交
1381
        }
1382
    }
1383 1384
}

1385 1386
static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
                      TCGv r_cond)
1387 1388
{
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1389 1390
    target_ulong target = dc->pc + offset;

1391
    if (cond == 0x0) {
B
blueswir1 已提交
1392 1393 1394 1395 1396 1397 1398 1399
        /* 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;
        }
1400
    } else if (cond == 0x8) {
B
blueswir1 已提交
1401 1402 1403 1404 1405 1406 1407
        /* unconditional taken */
        if (a) {
            dc->pc = target;
            dc->npc = dc->pc + 4;
        } else {
            dc->pc = dc->npc;
            dc->npc = target;
1408
            tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
blueswir1 已提交
1409
        }
1410
    } else {
1411 1412
        flush_cond(dc, r_cond);
        gen_fcond(r_cond, cc, cond);
B
blueswir1 已提交
1413
        if (a) {
1414
            gen_branch_a(dc, target, dc->npc, r_cond);
1415
            dc->is_br = 1;
B
blueswir1 已提交
1416
        } else {
1417 1418
            dc->pc = dc->npc;
            dc->jump_pc[0] = target;
1419 1420 1421 1422 1423 1424 1425
            if (unlikely(dc->npc == DYNAMIC_PC)) {
                dc->jump_pc[1] = DYNAMIC_PC;
                tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
            } else {
                dc->jump_pc[1] = dc->npc + 4;
                dc->npc = JUMP_PC;
            }
B
blueswir1 已提交
1426
        }
1427 1428 1429
    }
}

B
bellard 已提交
1430
#ifdef TARGET_SPARC64
1431 1432
static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
                          TCGv r_cond, TCGv r_reg)
1433
{
B
bellard 已提交
1434 1435 1436
    unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
    target_ulong target = dc->pc + offset;

1437 1438
    flush_cond(dc, r_cond);
    gen_cond_reg(r_cond, cond, r_reg);
B
bellard 已提交
1439
    if (a) {
1440
        gen_branch_a(dc, target, dc->npc, r_cond);
B
blueswir1 已提交
1441
        dc->is_br = 1;
B
bellard 已提交
1442
    } else {
B
blueswir1 已提交
1443 1444
        dc->pc = dc->npc;
        dc->jump_pc[0] = target;
1445 1446 1447 1448 1449 1450 1451
        if (unlikely(dc->npc == DYNAMIC_PC)) {
            dc->jump_pc[1] = DYNAMIC_PC;
            tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
        } else {
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
        }
B
bellard 已提交
1452
    }
1453 1454
}

P
pbrook 已提交
1455
static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1456
{
B
blueswir1 已提交
1457 1458
    switch (fccno) {
    case 0:
1459
        gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1460 1461
        break;
    case 1:
1462
        gen_helper_fcmps_fcc1(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1463 1464
        break;
    case 2:
1465
        gen_helper_fcmps_fcc2(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1466 1467
        break;
    case 3:
1468
        gen_helper_fcmps_fcc3(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1469 1470
        break;
    }
1471 1472
}

1473
static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1474
{
P
pbrook 已提交
1475 1476
    switch (fccno) {
    case 0:
1477
        gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1478 1479
        break;
    case 1:
1480
        gen_helper_fcmpd_fcc1(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1481 1482
        break;
    case 2:
1483
        gen_helper_fcmpd_fcc2(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1484 1485
        break;
    case 3:
1486
        gen_helper_fcmpd_fcc3(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1487 1488
        break;
    }
1489 1490 1491 1492
}

static inline void gen_op_fcmpq(int fccno)
{
P
pbrook 已提交
1493 1494
    switch (fccno) {
    case 0:
1495
        gen_helper_fcmpq(cpu_env);
P
pbrook 已提交
1496 1497
        break;
    case 1:
1498
        gen_helper_fcmpq_fcc1(cpu_env);
P
pbrook 已提交
1499 1500
        break;
    case 2:
1501
        gen_helper_fcmpq_fcc2(cpu_env);
P
pbrook 已提交
1502 1503
        break;
    case 3:
1504
        gen_helper_fcmpq_fcc3(cpu_env);
P
pbrook 已提交
1505 1506
        break;
    }
1507 1508
}

P
pbrook 已提交
1509
static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1510
{
B
blueswir1 已提交
1511 1512
    switch (fccno) {
    case 0:
1513
        gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1514 1515
        break;
    case 1:
1516
        gen_helper_fcmpes_fcc1(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1517 1518
        break;
    case 2:
1519
        gen_helper_fcmpes_fcc2(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1520 1521
        break;
    case 3:
1522
        gen_helper_fcmpes_fcc3(cpu_env, r_rs1, r_rs2);
B
blueswir1 已提交
1523 1524
        break;
    }
1525 1526
}

1527
static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1528
{
P
pbrook 已提交
1529 1530
    switch (fccno) {
    case 0:
1531
        gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1532 1533
        break;
    case 1:
1534
        gen_helper_fcmped_fcc1(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1535 1536
        break;
    case 2:
1537
        gen_helper_fcmped_fcc2(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1538 1539
        break;
    case 3:
1540
        gen_helper_fcmped_fcc3(cpu_env, r_rs1, r_rs2);
P
pbrook 已提交
1541 1542
        break;
    }
1543 1544 1545 1546
}

static inline void gen_op_fcmpeq(int fccno)
{
P
pbrook 已提交
1547 1548
    switch (fccno) {
    case 0:
1549
        gen_helper_fcmpeq(cpu_env);
P
pbrook 已提交
1550 1551
        break;
    case 1:
1552
        gen_helper_fcmpeq_fcc1(cpu_env);
P
pbrook 已提交
1553 1554
        break;
    case 2:
1555
        gen_helper_fcmpeq_fcc2(cpu_env);
P
pbrook 已提交
1556 1557
        break;
    case 3:
1558
        gen_helper_fcmpeq_fcc3(cpu_env);
P
pbrook 已提交
1559 1560
        break;
    }
1561 1562 1563 1564
}

#else

B
blueswir1 已提交
1565
static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
1566
{
1567
    gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
1568 1569
}

1570
static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1571
{
1572
    gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
1573 1574 1575 1576
}

static inline void gen_op_fcmpq(int fccno)
{
1577
    gen_helper_fcmpq(cpu_env);
1578 1579
}

B
blueswir1 已提交
1580
static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
1581
{
1582
    gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
1583 1584
}

1585
static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1586
{
1587
    gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
1588 1589 1590 1591
}

static inline void gen_op_fcmpeq(int fccno)
{
1592
    gen_helper_fcmpeq(cpu_env);
1593 1594 1595
}
#endif

B
blueswir1 已提交
1596 1597
static inline void gen_op_fpexception_im(int fsr_flags)
{
P
pbrook 已提交
1598
    TCGv_i32 r_const;
B
blueswir1 已提交
1599

1600
    tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
B
blueswir1 已提交
1601
    tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
B
blueswir1 已提交
1602
    r_const = tcg_const_i32(TT_FP_EXCP);
1603
    gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
1604
    tcg_temp_free_i32(r_const);
B
blueswir1 已提交
1605 1606
}

1607
static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
B
bellard 已提交
1608 1609 1610
{
#if !defined(CONFIG_USER_ONLY)
    if (!dc->fpu_enabled) {
P
pbrook 已提交
1611
        TCGv_i32 r_const;
B
blueswir1 已提交
1612

1613
        save_state(dc, r_cond);
B
blueswir1 已提交
1614
        r_const = tcg_const_i32(TT_NFPU_INSN);
1615
        gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
1616
        tcg_temp_free_i32(r_const);
B
bellard 已提交
1617 1618 1619 1620 1621 1622 1623
        dc->is_br = 1;
        return 1;
    }
#endif
    return 0;
}

1624 1625
static inline void gen_op_clear_ieee_excp_and_FTT(void)
{
1626
    tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
1627 1628
}

1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
static inline void gen_fop_FF(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32))
{
    TCGv_i32 dst, src;

    src = gen_load_fpr_F(dc, rs);
    dst = gen_dest_fpr_F();

    gen(dst, cpu_env, src);

    gen_store_fpr_F(dc, rd, dst);
}

static inline void gen_ne_fop_FF(DisasContext *dc, int rd, int rs,
                                 void (*gen)(TCGv_i32, TCGv_i32))
{
    TCGv_i32 dst, src;

    src = gen_load_fpr_F(dc, rs);
    dst = gen_dest_fpr_F();

    gen(dst, src);

    gen_store_fpr_F(dc, rd, dst);
}

static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
                        void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32))
{
    TCGv_i32 dst, src1, src2;

    src1 = gen_load_fpr_F(dc, rs1);
    src2 = gen_load_fpr_F(dc, rs2);
    dst = gen_dest_fpr_F();

    gen(dst, cpu_env, src1, src2);

    gen_store_fpr_F(dc, rd, dst);
}

#ifdef TARGET_SPARC64
static inline void gen_ne_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
                                  void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
{
    TCGv_i32 dst, src1, src2;

    src1 = gen_load_fpr_F(dc, rs1);
    src2 = gen_load_fpr_F(dc, rs2);
    dst = gen_dest_fpr_F();

    gen(dst, src1, src2);

    gen_store_fpr_F(dc, rd, dst);
}
#endif

static inline void gen_fop_DD(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64))
{
    TCGv_i64 dst, src;

    src = gen_load_fpr_D(dc, rs);
    dst = gen_dest_fpr_D();

    gen(dst, cpu_env, src);

    gen_store_fpr_D(dc, rd, dst);
}

#ifdef TARGET_SPARC64
static inline void gen_ne_fop_DD(DisasContext *dc, int rd, int rs,
                                 void (*gen)(TCGv_i64, TCGv_i64))
{
    TCGv_i64 dst, src;

    src = gen_load_fpr_D(dc, rs);
    dst = gen_dest_fpr_D();

    gen(dst, src);

    gen_store_fpr_D(dc, rd, dst);
}
#endif

static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
                        void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64))
{
    TCGv_i64 dst, src1, src2;

    src1 = gen_load_fpr_D(dc, rs1);
    src2 = gen_load_fpr_D(dc, rs2);
    dst = gen_dest_fpr_D();

    gen(dst, cpu_env, src1, src2);

    gen_store_fpr_D(dc, rd, dst);
}

#ifdef TARGET_SPARC64
static inline void gen_ne_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
                                  void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
{
    TCGv_i64 dst, src1, src2;

    src1 = gen_load_fpr_D(dc, rs1);
    src2 = gen_load_fpr_D(dc, rs2);
    dst = gen_dest_fpr_D();

    gen(dst, src1, src2);

    gen_store_fpr_D(dc, rd, dst);
}
R
Richard Henderson 已提交
1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755

static inline void gen_ne_fop_DDDD(DisasContext *dc, int rd, int rs1, int rs2,
                           void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
{
    TCGv_i64 dst, src0, src1, src2;

    src1 = gen_load_fpr_D(dc, rs1);
    src2 = gen_load_fpr_D(dc, rs2);
    src0 = gen_load_fpr_D(dc, rd);
    dst = gen_dest_fpr_D();

    gen(dst, src0, src1, src2);

    gen_store_fpr_D(dc, rd, dst);
}
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
#endif

static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_ptr))
{
    gen_op_load_fpr_QT1(QFPREG(rs));

    gen(cpu_env);

    gen_op_store_QT0_fpr(QFPREG(rd));
    gen_update_fprs_dirty(QFPREG(rd));
}

#ifdef TARGET_SPARC64
static inline void gen_ne_fop_QQ(DisasContext *dc, int rd, int rs,
                                 void (*gen)(TCGv_ptr))
{
    gen_op_load_fpr_QT1(QFPREG(rs));

    gen(cpu_env);

    gen_op_store_QT0_fpr(QFPREG(rd));
    gen_update_fprs_dirty(QFPREG(rd));
}
#endif

static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2,
                               void (*gen)(TCGv_ptr))
{
    gen_op_load_fpr_QT0(QFPREG(rs1));
    gen_op_load_fpr_QT1(QFPREG(rs2));

    gen(cpu_env);

    gen_op_store_QT0_fpr(QFPREG(rd));
    gen_update_fprs_dirty(QFPREG(rd));
}

static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2,
                        void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32, TCGv_i32))
{
    TCGv_i64 dst;
    TCGv_i32 src1, src2;

    src1 = gen_load_fpr_F(dc, rs1);
    src2 = gen_load_fpr_F(dc, rs2);
    dst = gen_dest_fpr_D();

    gen(dst, cpu_env, src1, src2);

    gen_store_fpr_D(dc, rd, dst);
}

static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2,
                               void (*gen)(TCGv_ptr, TCGv_i64, TCGv_i64))
{
    TCGv_i64 src1, src2;

    src1 = gen_load_fpr_D(dc, rs1);
    src2 = gen_load_fpr_D(dc, rs2);

    gen(cpu_env, src1, src2);

    gen_op_store_QT0_fpr(QFPREG(rd));
    gen_update_fprs_dirty(QFPREG(rd));
}

#ifdef TARGET_SPARC64
static inline void gen_fop_DF(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
{
    TCGv_i64 dst;
    TCGv_i32 src;

    src = gen_load_fpr_F(dc, rs);
    dst = gen_dest_fpr_D();

    gen(dst, cpu_env, src);

    gen_store_fpr_D(dc, rd, dst);
}
#endif

static inline void gen_ne_fop_DF(DisasContext *dc, int rd, int rs,
                                 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
{
    TCGv_i64 dst;
    TCGv_i32 src;

    src = gen_load_fpr_F(dc, rs);
    dst = gen_dest_fpr_D();

    gen(dst, cpu_env, src);

    gen_store_fpr_D(dc, rd, dst);
}

static inline void gen_fop_FD(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i64))
{
    TCGv_i32 dst;
    TCGv_i64 src;

    src = gen_load_fpr_D(dc, rs);
    dst = gen_dest_fpr_F();

    gen(dst, cpu_env, src);

    gen_store_fpr_F(dc, rd, dst);
}

static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_i32, TCGv_ptr))
{
    TCGv_i32 dst;

    gen_op_load_fpr_QT1(QFPREG(rs));
    dst = gen_dest_fpr_F();

    gen(dst, cpu_env);

    gen_store_fpr_F(dc, rd, dst);
}

static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs,
                              void (*gen)(TCGv_i64, TCGv_ptr))
{
    TCGv_i64 dst;

    gen_op_load_fpr_QT1(QFPREG(rs));
    dst = gen_dest_fpr_D();

    gen(dst, cpu_env);

    gen_store_fpr_D(dc, rd, dst);
}

static inline void gen_ne_fop_QF(DisasContext *dc, int rd, int rs,
                                 void (*gen)(TCGv_ptr, TCGv_i32))
{
    TCGv_i32 src;

    src = gen_load_fpr_F(dc, rs);

    gen(cpu_env, src);

    gen_op_store_QT0_fpr(QFPREG(rd));
    gen_update_fprs_dirty(QFPREG(rd));
}

static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
                                 void (*gen)(TCGv_ptr, TCGv_i64))
{
    TCGv_i64 src;

    src = gen_load_fpr_D(dc, rs);

    gen(cpu_env, src);

    gen_op_store_QT0_fpr(QFPREG(rd));
    gen_update_fprs_dirty(QFPREG(rd));
}

B
blueswir1 已提交
1919 1920
/* asi moves */
#ifdef TARGET_SPARC64
P
pbrook 已提交
1921
static inline TCGv_i32 gen_get_asi(int insn, TCGv r_addr)
B
blueswir1 已提交
1922
{
1923
    int asi;
P
pbrook 已提交
1924
    TCGv_i32 r_asi;
B
blueswir1 已提交
1925 1926

    if (IS_IMM) {
P
pbrook 已提交
1927
        r_asi = tcg_temp_new_i32();
1928
        tcg_gen_mov_i32(r_asi, cpu_asi);
B
blueswir1 已提交
1929 1930
    } else {
        asi = GET_FIELD(insn, 19, 26);
1931
        r_asi = tcg_const_i32(asi);
B
blueswir1 已提交
1932
    }
1933 1934 1935
    return r_asi;
}

B
blueswir1 已提交
1936 1937
static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
                              int sign)
1938
{
P
pbrook 已提交
1939
    TCGv_i32 r_asi, r_size, r_sign;
1940

1941
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1942 1943
    r_size = tcg_const_i32(size);
    r_sign = tcg_const_i32(sign);
P
pbrook 已提交
1944 1945 1946 1947
    gen_helper_ld_asi(dst, addr, r_asi, r_size, r_sign);
    tcg_temp_free_i32(r_sign);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1948 1949
}

1950
static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
B
blueswir1 已提交
1951
{
P
pbrook 已提交
1952
    TCGv_i32 r_asi, r_size;
B
blueswir1 已提交
1953

1954
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1955
    r_size = tcg_const_i32(size);
P
pbrook 已提交
1956 1957 1958
    gen_helper_st_asi(addr, src, r_asi, r_size);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1959 1960
}

1961
static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
B
blueswir1 已提交
1962
{
P
pbrook 已提交
1963
    TCGv_i32 r_asi, r_size, r_rd;
B
blueswir1 已提交
1964

1965
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1966 1967
    r_size = tcg_const_i32(size);
    r_rd = tcg_const_i32(rd);
P
pbrook 已提交
1968 1969 1970 1971
    gen_helper_ldf_asi(addr, r_asi, r_size, r_rd);
    tcg_temp_free_i32(r_rd);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1972 1973
}

1974
static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
B
blueswir1 已提交
1975
{
P
pbrook 已提交
1976
    TCGv_i32 r_asi, r_size, r_rd;
B
blueswir1 已提交
1977

1978
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1979 1980
    r_size = tcg_const_i32(size);
    r_rd = tcg_const_i32(rd);
P
pbrook 已提交
1981 1982 1983 1984
    gen_helper_stf_asi(addr, r_asi, r_size, r_rd);
    tcg_temp_free_i32(r_rd);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1985 1986
}

1987
static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
B
blueswir1 已提交
1988
{
P
pbrook 已提交
1989
    TCGv_i32 r_asi, r_size, r_sign;
B
blueswir1 已提交
1990

1991
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1992 1993
    r_size = tcg_const_i32(4);
    r_sign = tcg_const_i32(0);
P
pbrook 已提交
1994 1995 1996 1997 1998
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
    tcg_temp_free_i32(r_sign);
    gen_helper_st_asi(addr, dst, r_asi, r_size);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1999
    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
B
blueswir1 已提交
2000 2001
}

B
blueswir1 已提交
2002
static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
B
blueswir1 已提交
2003
{
P
pbrook 已提交
2004
    TCGv_i32 r_asi, r_rd;
B
blueswir1 已提交
2005

2006
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
2007
    r_rd = tcg_const_i32(rd);
P
pbrook 已提交
2008 2009 2010
    gen_helper_ldda_asi(addr, r_asi, r_rd);
    tcg_temp_free_i32(r_rd);
    tcg_temp_free_i32(r_asi);
2011 2012
}

2013
static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
2014
{
P
pbrook 已提交
2015
    TCGv_i32 r_asi, r_size;
2016 2017

    gen_movl_reg_TN(rd + 1, cpu_tmp0);
2018
    tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
2019
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
2020
    r_size = tcg_const_i32(8);
P
pbrook 已提交
2021 2022 2023
    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
2024 2025
}

B
blueswir1 已提交
2026 2027
static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
                               int rd)
B
blueswir1 已提交
2028
{
P
pbrook 已提交
2029 2030
    TCGv r_val1;
    TCGv_i32 r_asi;
B
blueswir1 已提交
2031

P
pbrook 已提交
2032
    r_val1 = tcg_temp_new();
B
blueswir1 已提交
2033
    gen_movl_reg_TN(rd, r_val1);
2034
    r_asi = gen_get_asi(insn, addr);
P
pbrook 已提交
2035 2036
    gen_helper_cas_asi(dst, addr, r_val1, val2, r_asi);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
2037
    tcg_temp_free(r_val1);
B
blueswir1 已提交
2038 2039
}

B
blueswir1 已提交
2040 2041
static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
                                int rd)
B
blueswir1 已提交
2042
{
P
pbrook 已提交
2043
    TCGv_i32 r_asi;
B
blueswir1 已提交
2044

B
blueswir1 已提交
2045
    gen_movl_reg_TN(rd, cpu_tmp64);
2046
    r_asi = gen_get_asi(insn, addr);
P
pbrook 已提交
2047 2048
    gen_helper_casx_asi(dst, addr, cpu_tmp64, val2, r_asi);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
2049 2050 2051 2052
}

#elif !defined(CONFIG_USER_ONLY)

B
blueswir1 已提交
2053 2054
static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
                              int sign)
B
blueswir1 已提交
2055
{
P
pbrook 已提交
2056
    TCGv_i32 r_asi, r_size, r_sign;
B
blueswir1 已提交
2057

B
blueswir1 已提交
2058 2059 2060
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(size);
    r_sign = tcg_const_i32(sign);
P
pbrook 已提交
2061
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
B
blueswir1 已提交
2062 2063 2064
    tcg_temp_free(r_sign);
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
2065
    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
B
blueswir1 已提交
2066 2067
}

2068
static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
B
blueswir1 已提交
2069
{
P
pbrook 已提交
2070
    TCGv_i32 r_asi, r_size;
B
blueswir1 已提交
2071

2072
    tcg_gen_extu_tl_i64(cpu_tmp64, src);
B
blueswir1 已提交
2073 2074
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(size);
P
pbrook 已提交
2075
    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
B
blueswir1 已提交
2076 2077
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
2078 2079
}

2080
static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
B
blueswir1 已提交
2081
{
P
pbrook 已提交
2082 2083
    TCGv_i32 r_asi, r_size, r_sign;
    TCGv_i64 r_val;
B
blueswir1 已提交
2084

B
blueswir1 已提交
2085 2086 2087
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(4);
    r_sign = tcg_const_i32(0);
P
pbrook 已提交
2088
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
B
blueswir1 已提交
2089
    tcg_temp_free(r_sign);
P
pbrook 已提交
2090 2091 2092 2093
    r_val = tcg_temp_new_i64();
    tcg_gen_extu_tl_i64(r_val, dst);
    gen_helper_st_asi(addr, r_val, r_asi, r_size);
    tcg_temp_free_i64(r_val);
B
blueswir1 已提交
2094 2095
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
2096
    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
B
blueswir1 已提交
2097 2098
}

B
blueswir1 已提交
2099
static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
B
blueswir1 已提交
2100
{
P
pbrook 已提交
2101
    TCGv_i32 r_asi, r_size, r_sign;
B
blueswir1 已提交
2102

B
blueswir1 已提交
2103 2104 2105
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(8);
    r_sign = tcg_const_i32(0);
P
pbrook 已提交
2106
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
B
blueswir1 已提交
2107 2108 2109
    tcg_temp_free(r_sign);
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
2110 2111
    tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
    gen_movl_TN_reg(rd + 1, cpu_tmp0);
B
blueswir1 已提交
2112
    tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
2113
    tcg_gen_trunc_i64_tl(hi, cpu_tmp64);
B
blueswir1 已提交
2114
    gen_movl_TN_reg(rd, hi);
2115 2116
}

2117
static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
2118
{
P
pbrook 已提交
2119
    TCGv_i32 r_asi, r_size;
2120 2121

    gen_movl_reg_TN(rd + 1, cpu_tmp0);
2122
    tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
B
blueswir1 已提交
2123 2124
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(8);
P
pbrook 已提交
2125
    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
B
blueswir1 已提交
2126 2127
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
2128 2129 2130 2131
}
#endif

#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2132
static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
B
blueswir1 已提交
2133
{
P
pbrook 已提交
2134 2135
    TCGv_i64 r_val;
    TCGv_i32 r_asi, r_size;
B
blueswir1 已提交
2136

2137
    gen_ld_asi(dst, addr, insn, 1, 0);
B
blueswir1 已提交
2138

B
blueswir1 已提交
2139 2140 2141
    r_val = tcg_const_i64(0xffULL);
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(1);
P
pbrook 已提交
2142 2143 2144 2145
    gen_helper_st_asi(addr, r_val, r_asi, r_size);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
    tcg_temp_free_i64(r_val);
B
blueswir1 已提交
2146 2147 2148
}
#endif

2149 2150 2151 2152 2153 2154
static inline TCGv get_src1(unsigned int insn, TCGv def)
{
    TCGv r_rs1 = def;
    unsigned int rs1;

    rs1 = GET_FIELD(insn, 13, 17);
2155 2156 2157
    if (rs1 == 0) {
        tcg_gen_movi_tl(def, 0);
    } else if (rs1 < 8) {
2158
        r_rs1 = cpu_gregs[rs1];
2159
    } else {
2160
        tcg_gen_ld_tl(def, cpu_regwptr, (rs1 - 8) * sizeof(target_ulong));
2161
    }
2162 2163 2164
    return r_rs1;
}

B
blueswir1 已提交
2165 2166 2167 2168 2169
static inline TCGv get_src2(unsigned int insn, TCGv def)
{
    TCGv r_rs2 = def;

    if (IS_IMM) { /* immediate */
2170 2171
        target_long simm = GET_FIELDs(insn, 19, 31);
        tcg_gen_movi_tl(def, simm);
B
blueswir1 已提交
2172
    } else { /* register */
2173 2174 2175 2176
        unsigned int rs2 = GET_FIELD(insn, 27, 31);
        if (rs2 == 0) {
            tcg_gen_movi_tl(def, 0);
        } else if (rs2 < 8) {
B
blueswir1 已提交
2177
            r_rs2 = cpu_gregs[rs2];
2178
        } else {
B
blueswir1 已提交
2179
            tcg_gen_ld_tl(def, cpu_regwptr, (rs2 - 8) * sizeof(target_ulong));
2180
        }
B
blueswir1 已提交
2181 2182 2183 2184
    }
    return r_rs2;
}

2185 2186 2187
#ifdef TARGET_SPARC64
static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
{
2188
    TCGv_i32 r_tl = tcg_temp_new_i32();
2189 2190

    /* load env->tl into r_tl */
2191
    tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
2192 2193

    /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2194
    tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2195 2196

    /* calculate offset to current trap state from env->ts, reuse r_tl */
2197
    tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2198 2199 2200
    tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUState, ts));

    /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2201 2202 2203 2204
    {
        TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
        tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
        tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2205
        tcg_temp_free_ptr(r_tl_tmp);
2206
    }
2207

2208
    tcg_temp_free_i32(r_tl);
2209 2210 2211
}
#endif

B
blueswir1 已提交
2212
#define CHECK_IU_FEATURE(dc, FEATURE)                      \
2213
    if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
B
blueswir1 已提交
2214 2215
        goto illegal_insn;
#define CHECK_FPU_FEATURE(dc, FEATURE)                     \
2216
    if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
B
blueswir1 已提交
2217 2218
        goto nfpu_insn;

B
bellard 已提交
2219
/* before an instruction, dc->pc must be static */
2220 2221 2222
static void disas_sparc_insn(DisasContext * dc)
{
    unsigned int insn, opc, rs1, rs2, rd;
2223
    TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
2224
    TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
2225
    TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
B
Blue Swirl 已提交
2226
    target_long simm;
2227

2228
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
B
blueswir1 已提交
2229
        tcg_gen_debug_insn_start(dc->pc);
B
bellard 已提交
2230
    insn = ldl_code(dc->pc);
2231
    opc = GET_FIELD(insn, 0, 1);
2232

2233
    rd = GET_FIELD(insn, 2, 6);
2234

2235 2236
    cpu_tmp1 = cpu_src1 = tcg_temp_new();
    cpu_tmp2 = cpu_src2 = tcg_temp_new();
2237

2238
    switch (opc) {
B
blueswir1 已提交
2239 2240 2241 2242 2243
    case 0:                     /* branches/sethi */
        {
            unsigned int xop = GET_FIELD(insn, 7, 9);
            int32_t target;
            switch (xop) {
B
bellard 已提交
2244
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2245 2246 2247 2248 2249
            case 0x1:           /* V9 BPcc */
                {
                    int cc;

                    target = GET_FIELD_SP(insn, 0, 18);
2250
                    target = sign_extend(target, 19);
B
blueswir1 已提交
2251 2252 2253
                    target <<= 2;
                    cc = GET_FIELD_SP(insn, 20, 21);
                    if (cc == 0)
2254
                        do_branch(dc, target, insn, 0, cpu_cond);
B
blueswir1 已提交
2255
                    else if (cc == 2)
2256
                        do_branch(dc, target, insn, 1, cpu_cond);
B
blueswir1 已提交
2257 2258 2259 2260 2261 2262 2263
                    else
                        goto illegal_insn;
                    goto jmp_insn;
                }
            case 0x3:           /* V9 BPr */
                {
                    target = GET_FIELD_SP(insn, 0, 13) |
2264
                        (GET_FIELD_SP(insn, 20, 21) << 14);
B
blueswir1 已提交
2265 2266
                    target = sign_extend(target, 16);
                    target <<= 2;
2267
                    cpu_src1 = get_src1(insn, cpu_src1);
2268
                    do_branch_reg(dc, target, insn, cpu_cond, cpu_src1);
B
blueswir1 已提交
2269 2270 2271 2272 2273
                    goto jmp_insn;
                }
            case 0x5:           /* V9 FBPcc */
                {
                    int cc = GET_FIELD_SP(insn, 20, 21);
2274
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2275
                        goto jmp_insn;
B
blueswir1 已提交
2276 2277 2278
                    target = GET_FIELD_SP(insn, 0, 18);
                    target = sign_extend(target, 19);
                    target <<= 2;
2279
                    do_fbranch(dc, target, insn, cc, cpu_cond);
B
blueswir1 已提交
2280 2281
                    goto jmp_insn;
                }
2282
#else
B
blueswir1 已提交
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292
            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;
2293
                    do_branch(dc, target, insn, 0, cpu_cond);
B
blueswir1 已提交
2294 2295 2296 2297
                    goto jmp_insn;
                }
            case 0x6:           /* FBN+x */
                {
2298
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2299
                        goto jmp_insn;
B
blueswir1 已提交
2300 2301 2302
                    target = GET_FIELD(insn, 10, 31);
                    target = sign_extend(target, 22);
                    target <<= 2;
2303
                    do_fbranch(dc, target, insn, 0, cpu_cond);
B
blueswir1 已提交
2304 2305 2306 2307 2308
                    goto jmp_insn;
                }
            case 0x4:           /* SETHI */
                if (rd) { // nop
                    uint32_t value = GET_FIELD(insn, 10, 31);
B
blueswir1 已提交
2309 2310 2311 2312 2313
                    TCGv r_const;

                    r_const = tcg_const_tl(value << 10);
                    gen_movl_TN_reg(rd, r_const);
                    tcg_temp_free(r_const);
B
blueswir1 已提交
2314 2315 2316 2317
                }
                break;
            case 0x0:           /* UNIMPL */
            default:
B
bellard 已提交
2318
                goto illegal_insn;
B
blueswir1 已提交
2319 2320 2321 2322
            }
            break;
        }
        break;
B
Blue Swirl 已提交
2323 2324
    case 1:                     /*CALL*/
        {
B
blueswir1 已提交
2325
            target_long target = GET_FIELDs(insn, 2, 31) << 2;
B
blueswir1 已提交
2326
            TCGv r_const;
2327

B
blueswir1 已提交
2328 2329 2330
            r_const = tcg_const_tl(dc->pc);
            gen_movl_TN_reg(15, r_const);
            tcg_temp_free(r_const);
B
blueswir1 已提交
2331
            target += dc->pc;
2332
            gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
2333 2334 2335 2336 2337 2338 2339
            dc->npc = target;
        }
        goto jmp_insn;
    case 2:                     /* FPU & Logical Operations */
        {
            unsigned int xop = GET_FIELD(insn, 7, 12);
            if (xop == 0x3a) {  /* generate trap */
2340
                int cond;
B
bellard 已提交
2341

2342
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
2343 2344
                if (IS_IMM) {
                    rs2 = GET_FIELD(insn, 25, 31);
2345
                    tcg_gen_addi_tl(cpu_dst, cpu_src1, rs2);
2346 2347
                } else {
                    rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
2348
                    if (rs2 != 0) {
2349 2350
                        gen_movl_reg_TN(rs2, cpu_src2);
                        tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
2351 2352
                    } else
                        tcg_gen_mov_tl(cpu_dst, cpu_src1);
2353
                }
F
Fabien Chouteau 已提交
2354

2355
                cond = GET_FIELD(insn, 3, 6);
F
Fabien Chouteau 已提交
2356
                if (cond == 0x8) { /* Trap Always */
2357
                    save_state(dc, cpu_cond);
B
blueswir1 已提交
2358 2359 2360 2361 2362 2363
                    if ((dc->def->features & CPU_FEATURE_HYPV) &&
                        supervisor(dc))
                        tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
                    else
                        tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
                    tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
P
pbrook 已提交
2364
                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
F
Fabien Chouteau 已提交
2365 2366 2367 2368 2369 2370 2371

                    if (rs2 == 0 &&
                        dc->def->features & CPU_FEATURE_TA0_SHUTDOWN) {

                        gen_helper_shutdown();

                    } else {
2372
                        gen_helper_raise_exception(cpu_env, cpu_tmp32);
F
Fabien Chouteau 已提交
2373
                    }
2374
                } else if (cond != 0) {
P
pbrook 已提交
2375
                    TCGv r_cond = tcg_temp_new();
B
blueswir1 已提交
2376
                    int l1;
B
bellard 已提交
2377
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2378 2379
                    /* V9 icc/xcc */
                    int cc = GET_FIELD_SP(insn, 11, 12);
B
blueswir1 已提交
2380

2381
                    save_state(dc, cpu_cond);
B
blueswir1 已提交
2382
                    if (cc == 0)
2383
                        gen_cond(r_cond, 0, cond, dc);
B
blueswir1 已提交
2384
                    else if (cc == 2)
2385
                        gen_cond(r_cond, 1, cond, dc);
B
blueswir1 已提交
2386 2387
                    else
                        goto illegal_insn;
B
bellard 已提交
2388
#else
2389
                    save_state(dc, cpu_cond);
2390
                    gen_cond(r_cond, 0, cond, dc);
B
bellard 已提交
2391
#endif
B
blueswir1 已提交
2392 2393 2394 2395 2396 2397 2398 2399 2400
                    l1 = gen_new_label();
                    tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);

                    if ((dc->def->features & CPU_FEATURE_HYPV) &&
                        supervisor(dc))
                        tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
                    else
                        tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
                    tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
P
pbrook 已提交
2401
                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
2402
                    gen_helper_raise_exception(cpu_env, cpu_tmp32);
B
blueswir1 已提交
2403 2404

                    gen_set_label(l1);
B
blueswir1 已提交
2405
                    tcg_temp_free(r_cond);
2406
                }
B
bellard 已提交
2407
                gen_op_next_insn();
B
bellard 已提交
2408
                tcg_gen_exit_tb(0);
B
bellard 已提交
2409 2410
                dc->is_br = 1;
                goto jmp_insn;
2411 2412 2413 2414
            } else if (xop == 0x28) {
                rs1 = GET_FIELD(insn, 13, 17);
                switch(rs1) {
                case 0: /* rdy */
2415 2416 2417 2418 2419 2420 2421 2422 2423
#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 */
2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434
                    /* Read Asr17 */
                    if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
                        TCGv r_const;

                        /* Read Asr17 for a Leon3 monoprocessor */
                        r_const = tcg_const_tl((1 << 8)
                                               | (dc->def->nwindows - 1));
                        gen_movl_TN_reg(rd, r_const);
                        tcg_temp_free(r_const);
                        break;
                    }
2435
#endif
2436
                    gen_movl_TN_reg(rd, cpu_y);
2437
                    break;
B
bellard 已提交
2438
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2439
                case 0x2: /* V9 rdccr */
2440
                    gen_helper_compute_psr(cpu_env);
2441
                    gen_helper_rdccr(cpu_dst, cpu_env);
2442
                    gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2443
                    break;
B
blueswir1 已提交
2444
                case 0x3: /* V9 rdasi */
2445
                    tcg_gen_ext_i32_tl(cpu_dst, cpu_asi);
2446
                    gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2447
                    break;
B
blueswir1 已提交
2448
                case 0x4: /* V9 rdtick */
B
blueswir1 已提交
2449
                    {
P
pbrook 已提交
2450
                        TCGv_ptr r_tickptr;
B
blueswir1 已提交
2451

P
pbrook 已提交
2452
                        r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
2453 2454
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, tick));
P
pbrook 已提交
2455 2456
                        gen_helper_tick_get_count(cpu_dst, r_tickptr);
                        tcg_temp_free_ptr(r_tickptr);
2457
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2458
                    }
B
bellard 已提交
2459
                    break;
B
blueswir1 已提交
2460
                case 0x5: /* V9 rdpc */
B
blueswir1 已提交
2461 2462 2463 2464 2465 2466 2467
                    {
                        TCGv r_const;

                        r_const = tcg_const_tl(dc->pc);
                        gen_movl_TN_reg(rd, r_const);
                        tcg_temp_free(r_const);
                    }
B
blueswir1 已提交
2468 2469
                    break;
                case 0x6: /* V9 rdfprs */
2470
                    tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
2471
                    gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2472
                    break;
2473 2474
                case 0xf: /* V9 membar */
                    break; /* no effect */
B
blueswir1 已提交
2475
                case 0x13: /* Graphics Status */
2476
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2477
                        goto jmp_insn;
2478
                    gen_movl_TN_reg(rd, cpu_gsr);
B
bellard 已提交
2479
                    break;
2480 2481 2482 2483
                case 0x16: /* Softint */
                    tcg_gen_ext_i32_tl(cpu_dst, cpu_softint);
                    gen_movl_TN_reg(rd, cpu_dst);
                    break;
B
blueswir1 已提交
2484
                case 0x17: /* Tick compare */
2485
                    gen_movl_TN_reg(rd, cpu_tick_cmpr);
B
bellard 已提交
2486
                    break;
B
blueswir1 已提交
2487
                case 0x18: /* System tick */
B
blueswir1 已提交
2488
                    {
P
pbrook 已提交
2489
                        TCGv_ptr r_tickptr;
B
blueswir1 已提交
2490

P
pbrook 已提交
2491
                        r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
2492 2493
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, stick));
P
pbrook 已提交
2494 2495
                        gen_helper_tick_get_count(cpu_dst, r_tickptr);
                        tcg_temp_free_ptr(r_tickptr);
2496
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2497
                    }
B
bellard 已提交
2498
                    break;
B
blueswir1 已提交
2499
                case 0x19: /* System tick compare */
2500
                    gen_movl_TN_reg(rd, cpu_stick_cmpr);
B
bellard 已提交
2501
                    break;
B
blueswir1 已提交
2502 2503 2504 2505 2506
                case 0x10: /* Performance Control */
                case 0x11: /* Performance Instrumentation Counter */
                case 0x12: /* Dispatch Control */
                case 0x14: /* Softint set, WO */
                case 0x15: /* Softint clear, WO */
B
bellard 已提交
2507 2508
#endif
                default:
2509 2510
                    goto illegal_insn;
                }
2511
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
2512
            } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
B
bellard 已提交
2513
#ifndef TARGET_SPARC64
B
blueswir1 已提交
2514 2515
                if (!supervisor(dc))
                    goto priv_insn;
2516
                gen_helper_compute_psr(cpu_env);
2517
                dc->cc_op = CC_OP_FLAGS;
2518
                gen_helper_rdpsr(cpu_dst, cpu_env);
B
blueswir1 已提交
2519
#else
2520
                CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531
                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
2532
                    tcg_gen_mov_tl(cpu_dst, cpu_hintp);
B
blueswir1 已提交
2533 2534
                    break;
                case 5: // htba
2535
                    tcg_gen_mov_tl(cpu_dst, cpu_htba);
B
blueswir1 已提交
2536 2537
                    break;
                case 6: // hver
2538
                    tcg_gen_mov_tl(cpu_dst, cpu_hver);
B
blueswir1 已提交
2539 2540
                    break;
                case 31: // hstick_cmpr
2541
                    tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
B
blueswir1 已提交
2542 2543 2544 2545 2546
                    break;
                default:
                    goto illegal_insn;
                }
#endif
2547
                gen_movl_TN_reg(rd, cpu_dst);
2548
                break;
B
bellard 已提交
2549
            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
B
blueswir1 已提交
2550 2551
                if (!supervisor(dc))
                    goto priv_insn;
B
bellard 已提交
2552 2553
#ifdef TARGET_SPARC64
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2554 2555
                switch (rs1) {
                case 0: // tpc
2556
                    {
P
pbrook 已提交
2557
                        TCGv_ptr r_tsptr;
2558

P
pbrook 已提交
2559
                        r_tsptr = tcg_temp_new_ptr();
2560
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
P
pbrook 已提交
2561
                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2562
                                      offsetof(trap_state, tpc));
P
pbrook 已提交
2563
                        tcg_temp_free_ptr(r_tsptr);
2564
                    }
B
blueswir1 已提交
2565 2566
                    break;
                case 1: // tnpc
2567
                    {
P
pbrook 已提交
2568
                        TCGv_ptr r_tsptr;
2569

P
pbrook 已提交
2570
                        r_tsptr = tcg_temp_new_ptr();
2571
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
2572
                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2573
                                      offsetof(trap_state, tnpc));
P
pbrook 已提交
2574
                        tcg_temp_free_ptr(r_tsptr);
2575
                    }
B
blueswir1 已提交
2576 2577
                    break;
                case 2: // tstate
2578
                    {
P
pbrook 已提交
2579
                        TCGv_ptr r_tsptr;
2580

P
pbrook 已提交
2581
                        r_tsptr = tcg_temp_new_ptr();
2582
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
2583
                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2584
                                      offsetof(trap_state, tstate));
P
pbrook 已提交
2585
                        tcg_temp_free_ptr(r_tsptr);
2586
                    }
B
blueswir1 已提交
2587 2588
                    break;
                case 3: // tt
2589
                    {
P
pbrook 已提交
2590
                        TCGv_ptr r_tsptr;
2591

P
pbrook 已提交
2592
                        r_tsptr = tcg_temp_new_ptr();
2593
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
P
pbrook 已提交
2594
                        tcg_gen_ld_i32(cpu_tmp32, r_tsptr,
2595
                                       offsetof(trap_state, tt));
P
pbrook 已提交
2596 2597
                        tcg_temp_free_ptr(r_tsptr);
                        tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
2598
                    }
B
blueswir1 已提交
2599 2600
                    break;
                case 4: // tick
B
blueswir1 已提交
2601
                    {
P
pbrook 已提交
2602
                        TCGv_ptr r_tickptr;
B
blueswir1 已提交
2603

P
pbrook 已提交
2604
                        r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
2605 2606
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, tick));
P
pbrook 已提交
2607
                        gen_helper_tick_get_count(cpu_tmp0, r_tickptr);
2608
                        gen_movl_TN_reg(rd, cpu_tmp0);
P
pbrook 已提交
2609
                        tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
2610
                    }
B
blueswir1 已提交
2611 2612
                    break;
                case 5: // tba
2613
                    tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
B
blueswir1 已提交
2614 2615
                    break;
                case 6: // pstate
B
blueswir1 已提交
2616 2617
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, pstate));
2618
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2619 2620
                    break;
                case 7: // tl
B
blueswir1 已提交
2621 2622
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, tl));
2623
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2624 2625
                    break;
                case 8: // pil
B
blueswir1 已提交
2626 2627
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, psrpil));
2628
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2629 2630
                    break;
                case 9: // cwp
2631
                    gen_helper_rdcwp(cpu_tmp0, cpu_env);
B
blueswir1 已提交
2632 2633
                    break;
                case 10: // cansave
B
blueswir1 已提交
2634 2635
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, cansave));
2636
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2637 2638
                    break;
                case 11: // canrestore
B
blueswir1 已提交
2639 2640
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, canrestore));
2641
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2642 2643
                    break;
                case 12: // cleanwin
B
blueswir1 已提交
2644 2645
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, cleanwin));
2646
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2647 2648
                    break;
                case 13: // otherwin
B
blueswir1 已提交
2649 2650
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, otherwin));
2651
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2652 2653
                    break;
                case 14: // wstate
B
blueswir1 已提交
2654 2655
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, wstate));
2656
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2657
                    break;
B
blueswir1 已提交
2658
                case 16: // UA2005 gl
2659
                    CHECK_IU_FEATURE(dc, GL);
B
blueswir1 已提交
2660 2661
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, gl));
2662
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2663 2664
                    break;
                case 26: // UA2005 strand status
2665
                    CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
2666 2667
                    if (!hypervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
2668
                    tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
B
blueswir1 已提交
2669
                    break;
B
blueswir1 已提交
2670
                case 31: // ver
2671
                    tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
B
blueswir1 已提交
2672 2673 2674 2675 2676
                    break;
                case 15: // fq
                default:
                    goto illegal_insn;
                }
B
bellard 已提交
2677
#else
2678
                tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
B
bellard 已提交
2679
#endif
2680
                gen_movl_TN_reg(rd, cpu_tmp0);
2681
                break;
B
bellard 已提交
2682 2683
            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
2684
                save_state(dc, cpu_cond);
2685
                gen_helper_flushw(cpu_env);
B
bellard 已提交
2686
#else
B
blueswir1 已提交
2687 2688
                if (!supervisor(dc))
                    goto priv_insn;
2689
                gen_movl_TN_reg(rd, cpu_tbr);
B
bellard 已提交
2690
#endif
2691 2692
                break;
#endif
B
blueswir1 已提交
2693
            } else if (xop == 0x34) {   /* FPU Operations */
2694
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2695
                    goto jmp_insn;
B
blueswir1 已提交
2696
                gen_op_clear_ieee_excp_and_FTT();
2697
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2698 2699
                rs2 = GET_FIELD(insn, 27, 31);
                xop = GET_FIELD(insn, 18, 26);
B
Blue Swirl 已提交
2700
                save_state(dc, cpu_cond);
B
blueswir1 已提交
2701
                switch (xop) {
B
Blue Swirl 已提交
2702
                case 0x1: /* fmovs */
2703 2704
                    cpu_src1_32 = gen_load_fpr_F(dc, rs2);
                    gen_store_fpr_F(dc, rd, cpu_src1_32);
B
Blue Swirl 已提交
2705 2706
                    break;
                case 0x5: /* fnegs */
2707
                    gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
B
Blue Swirl 已提交
2708 2709
                    break;
                case 0x9: /* fabss */
2710
                    gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
B
Blue Swirl 已提交
2711 2712 2713
                    break;
                case 0x29: /* fsqrts */
                    CHECK_FPU_FEATURE(dc, FSQRT);
2714
                    gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
B
Blue Swirl 已提交
2715 2716 2717
                    break;
                case 0x2a: /* fsqrtd */
                    CHECK_FPU_FEATURE(dc, FSQRT);
2718
                    gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
B
Blue Swirl 已提交
2719 2720 2721
                    break;
                case 0x2b: /* fsqrtq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2722
                    gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
B
Blue Swirl 已提交
2723 2724
                    break;
                case 0x41: /* fadds */
2725
                    gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
B
Blue Swirl 已提交
2726 2727
                    break;
                case 0x42: /* faddd */
2728
                    gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
B
Blue Swirl 已提交
2729 2730 2731
                    break;
                case 0x43: /* faddq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2732
                    gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
B
Blue Swirl 已提交
2733 2734
                    break;
                case 0x45: /* fsubs */
2735
                    gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
B
Blue Swirl 已提交
2736 2737
                    break;
                case 0x46: /* fsubd */
2738
                    gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
B
Blue Swirl 已提交
2739 2740 2741
                    break;
                case 0x47: /* fsubq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2742
                    gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
B
Blue Swirl 已提交
2743 2744 2745
                    break;
                case 0x49: /* fmuls */
                    CHECK_FPU_FEATURE(dc, FMUL);
2746
                    gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
B
Blue Swirl 已提交
2747 2748 2749
                    break;
                case 0x4a: /* fmuld */
                    CHECK_FPU_FEATURE(dc, FMUL);
2750
                    gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
B
Blue Swirl 已提交
2751 2752 2753 2754
                    break;
                case 0x4b: /* fmulq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    CHECK_FPU_FEATURE(dc, FMUL);
2755
                    gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
B
Blue Swirl 已提交
2756 2757
                    break;
                case 0x4d: /* fdivs */
2758
                    gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
B
Blue Swirl 已提交
2759 2760
                    break;
                case 0x4e: /* fdivd */
2761
                    gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
B
Blue Swirl 已提交
2762 2763 2764
                    break;
                case 0x4f: /* fdivq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2765
                    gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
B
Blue Swirl 已提交
2766 2767 2768
                    break;
                case 0x69: /* fsmuld */
                    CHECK_FPU_FEATURE(dc, FSMULD);
2769
                    gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
B
Blue Swirl 已提交
2770 2771 2772
                    break;
                case 0x6e: /* fdmulq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2773
                    gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
B
Blue Swirl 已提交
2774 2775
                    break;
                case 0xc4: /* fitos */
2776
                    gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
B
Blue Swirl 已提交
2777 2778
                    break;
                case 0xc6: /* fdtos */
2779
                    gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
B
Blue Swirl 已提交
2780 2781 2782
                    break;
                case 0xc7: /* fqtos */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2783
                    gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
B
Blue Swirl 已提交
2784 2785
                    break;
                case 0xc8: /* fitod */
2786
                    gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
B
Blue Swirl 已提交
2787 2788
                    break;
                case 0xc9: /* fstod */
2789
                    gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
B
Blue Swirl 已提交
2790 2791 2792
                    break;
                case 0xcb: /* fqtod */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2793
                    gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
B
Blue Swirl 已提交
2794 2795 2796
                    break;
                case 0xcc: /* fitoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2797
                    gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
B
Blue Swirl 已提交
2798 2799 2800
                    break;
                case 0xcd: /* fstoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2801
                    gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
B
Blue Swirl 已提交
2802 2803 2804
                    break;
                case 0xce: /* fdtoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2805
                    gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
B
Blue Swirl 已提交
2806 2807
                    break;
                case 0xd1: /* fstoi */
2808
                    gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
B
Blue Swirl 已提交
2809 2810
                    break;
                case 0xd2: /* fdtoi */
2811
                    gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
B
Blue Swirl 已提交
2812 2813 2814
                    break;
                case 0xd3: /* fqtoi */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2815
                    gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
B
Blue Swirl 已提交
2816
                    break;
B
bellard 已提交
2817
#ifdef TARGET_SPARC64
B
Blue Swirl 已提交
2818
                case 0x2: /* V9 fmovd */
2819 2820
                    cpu_src1_64 = gen_load_fpr_D(dc, rs2);
                    gen_store_fpr_D(dc, rd, cpu_src1_64);
B
Blue Swirl 已提交
2821 2822 2823
                    break;
                case 0x3: /* V9 fmovq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2824
                    gen_move_Q(rd, rs2);
B
Blue Swirl 已提交
2825 2826
                    break;
                case 0x6: /* V9 fnegd */
2827
                    gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
B
Blue Swirl 已提交
2828 2829 2830
                    break;
                case 0x7: /* V9 fnegq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2831
                    gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
B
Blue Swirl 已提交
2832 2833
                    break;
                case 0xa: /* V9 fabsd */
2834
                    gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
B
Blue Swirl 已提交
2835 2836 2837
                    break;
                case 0xb: /* V9 fabsq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2838
                    gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
B
Blue Swirl 已提交
2839 2840
                    break;
                case 0x81: /* V9 fstox */
2841
                    gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
B
Blue Swirl 已提交
2842 2843
                    break;
                case 0x82: /* V9 fdtox */
2844
                    gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
B
Blue Swirl 已提交
2845 2846 2847
                    break;
                case 0x83: /* V9 fqtox */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2848
                    gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
B
Blue Swirl 已提交
2849 2850
                    break;
                case 0x84: /* V9 fxtos */
2851
                    gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
B
Blue Swirl 已提交
2852 2853
                    break;
                case 0x88: /* V9 fxtod */
2854
                    gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
B
Blue Swirl 已提交
2855 2856 2857
                    break;
                case 0x8c: /* V9 fxtoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
2858
                    gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
B
Blue Swirl 已提交
2859
                    break;
B
blueswir1 已提交
2860
#endif
B
Blue Swirl 已提交
2861 2862
                default:
                    goto illegal_insn;
B
blueswir1 已提交
2863 2864
                }
            } else if (xop == 0x35) {   /* FPU Operations */
B
bellard 已提交
2865
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2866
                int cond;
B
bellard 已提交
2867
#endif
2868
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2869
                    goto jmp_insn;
B
blueswir1 已提交
2870
                gen_op_clear_ieee_excp_and_FTT();
2871
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2872 2873
                rs2 = GET_FIELD(insn, 27, 31);
                xop = GET_FIELD(insn, 18, 26);
B
Blue Swirl 已提交
2874
                save_state(dc, cpu_cond);
B
bellard 已提交
2875
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2876
                if ((xop & 0x11f) == 0x005) { // V9 fmovsr
B
blueswir1 已提交
2877 2878 2879
                    int l1;

                    l1 = gen_new_label();
B
blueswir1 已提交
2880
                    cond = GET_FIELD_SP(insn, 14, 17);
2881
                    cpu_src1 = get_src1(insn, cpu_src1);
P
pbrook 已提交
2882 2883
                    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                       0, l1);
2884 2885
                    cpu_src1_32 = gen_load_fpr_F(dc, rs2);
                    gen_store_fpr_F(dc, rd, cpu_src1_32);
B
blueswir1 已提交
2886
                    gen_set_label(l1);
B
blueswir1 已提交
2887 2888
                    break;
                } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
B
blueswir1 已提交
2889 2890 2891
                    int l1;

                    l1 = gen_new_label();
B
blueswir1 已提交
2892
                    cond = GET_FIELD_SP(insn, 14, 17);
2893
                    cpu_src1 = get_src1(insn, cpu_src1);
P
pbrook 已提交
2894 2895
                    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                       0, l1);
2896 2897
                    cpu_src1_64 = gen_load_fpr_D(dc, rs2);
                    gen_store_fpr_D(dc, rd, cpu_src1_64);
B
blueswir1 已提交
2898
                    gen_set_label(l1);
B
blueswir1 已提交
2899 2900
                    break;
                } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
B
blueswir1 已提交
2901 2902
                    int l1;

B
blueswir1 已提交
2903
                    CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2904
                    l1 = gen_new_label();
B
blueswir1 已提交
2905
                    cond = GET_FIELD_SP(insn, 14, 17);
2906
                    cpu_src1 = get_src1(insn, cpu_src1);
P
pbrook 已提交
2907 2908
                    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                       0, l1);
2909
                    gen_move_Q(rd, rs2);
B
blueswir1 已提交
2910
                    gen_set_label(l1);
B
blueswir1 已提交
2911
                    break;
B
blueswir1 已提交
2912 2913 2914
                }
#endif
                switch (xop) {
B
bellard 已提交
2915
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2916
#define FMOVSCC(fcc)                                                    \
2917
                    {                                                   \
2918
                        TCGv r_cond;                                    \
2919 2920 2921
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2922
                        r_cond = tcg_temp_new();                        \
2923 2924
                        cond = GET_FIELD_SP(insn, 14, 17);              \
                        gen_fcond(r_cond, fcc, cond);                   \
P
pbrook 已提交
2925 2926
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
2927 2928
                        cpu_src1_32 = gen_load_fpr_F(dc, rs2);          \
                        gen_store_fpr_F(dc, rd, cpu_src1_32);           \
B
blueswir1 已提交
2929 2930 2931 2932 2933 2934 2935 2936 2937
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVDCC(fcc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2938
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2939 2940 2941 2942
                        cond = GET_FIELD_SP(insn, 14, 17);              \
                        gen_fcond(r_cond, fcc, cond);                   \
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
2943 2944
                        cpu_src1_64 = gen_load_fpr_D(dc, rs2);          \
                        gen_store_fpr_D(dc, rd, cpu_src1_64);           \
B
blueswir1 已提交
2945 2946 2947 2948 2949 2950 2951 2952 2953
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVQCC(fcc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2954
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2955 2956 2957 2958
                        cond = GET_FIELD_SP(insn, 14, 17);              \
                        gen_fcond(r_cond, fcc, cond);                   \
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
2959
                        gen_move_Q(rd, rs2);                            \
2960
                        gen_set_label(l1);                              \
B
blueswir1 已提交
2961
                        tcg_temp_free(r_cond);                          \
2962
                    }
B
blueswir1 已提交
2963
                    case 0x001: /* V9 fmovscc %fcc0 */
B
blueswir1 已提交
2964
                        FMOVSCC(0);
B
blueswir1 已提交
2965 2966
                        break;
                    case 0x002: /* V9 fmovdcc %fcc0 */
B
blueswir1 已提交
2967
                        FMOVDCC(0);
B
blueswir1 已提交
2968 2969
                        break;
                    case 0x003: /* V9 fmovqcc %fcc0 */
B
blueswir1 已提交
2970
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2971
                        FMOVQCC(0);
B
blueswir1 已提交
2972
                        break;
B
blueswir1 已提交
2973
                    case 0x041: /* V9 fmovscc %fcc1 */
B
blueswir1 已提交
2974
                        FMOVSCC(1);
B
blueswir1 已提交
2975 2976
                        break;
                    case 0x042: /* V9 fmovdcc %fcc1 */
B
blueswir1 已提交
2977
                        FMOVDCC(1);
B
blueswir1 已提交
2978 2979
                        break;
                    case 0x043: /* V9 fmovqcc %fcc1 */
B
blueswir1 已提交
2980
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2981
                        FMOVQCC(1);
B
blueswir1 已提交
2982
                        break;
B
blueswir1 已提交
2983
                    case 0x081: /* V9 fmovscc %fcc2 */
B
blueswir1 已提交
2984
                        FMOVSCC(2);
B
blueswir1 已提交
2985 2986
                        break;
                    case 0x082: /* V9 fmovdcc %fcc2 */
B
blueswir1 已提交
2987
                        FMOVDCC(2);
B
blueswir1 已提交
2988 2989
                        break;
                    case 0x083: /* V9 fmovqcc %fcc2 */
B
blueswir1 已提交
2990
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2991
                        FMOVQCC(2);
B
blueswir1 已提交
2992
                        break;
B
blueswir1 已提交
2993
                    case 0x0c1: /* V9 fmovscc %fcc3 */
B
blueswir1 已提交
2994
                        FMOVSCC(3);
B
blueswir1 已提交
2995 2996
                        break;
                    case 0x0c2: /* V9 fmovdcc %fcc3 */
B
blueswir1 已提交
2997
                        FMOVDCC(3);
B
blueswir1 已提交
2998 2999
                        break;
                    case 0x0c3: /* V9 fmovqcc %fcc3 */
B
blueswir1 已提交
3000
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
3001
                        FMOVQCC(3);
B
blueswir1 已提交
3002
                        break;
B
blueswir1 已提交
3003 3004 3005 3006 3007 3008 3009 3010 3011
#undef FMOVSCC
#undef FMOVDCC
#undef FMOVQCC
#define FMOVSCC(icc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
3012
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
3013
                        cond = GET_FIELD_SP(insn, 14, 17);              \
3014
                        gen_cond(r_cond, icc, cond, dc);                \
B
blueswir1 已提交
3015 3016
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
3017 3018
                        cpu_src1_32 = gen_load_fpr_F(dc, rs2);          \
                        gen_store_fpr_F(dc, rd, cpu_src1_32);           \
B
blueswir1 已提交
3019 3020 3021 3022 3023 3024 3025 3026 3027
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVDCC(icc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
3028
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
3029
                        cond = GET_FIELD_SP(insn, 14, 17);              \
3030
                        gen_cond(r_cond, icc, cond, dc);                \
B
blueswir1 已提交
3031 3032
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
3033 3034
                        cpu_src1_64 = gen_load_fpr_D(dc, rs2);          \
                        gen_store_fpr_D(dc, rd, cpu_src1_64);           \
3035
                        gen_update_fprs_dirty(DFPREG(rd));              \
B
blueswir1 已提交
3036 3037 3038 3039 3040 3041 3042 3043 3044
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVQCC(icc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
3045
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
3046
                        cond = GET_FIELD_SP(insn, 14, 17);              \
3047
                        gen_cond(r_cond, icc, cond, dc);                \
B
blueswir1 已提交
3048 3049
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
3050
                        gen_move_Q(rd, rs2);                            \
B
blueswir1 已提交
3051 3052 3053
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
3054

B
blueswir1 已提交
3055
                    case 0x101: /* V9 fmovscc %icc */
B
blueswir1 已提交
3056
                        FMOVSCC(0);
B
blueswir1 已提交
3057 3058
                        break;
                    case 0x102: /* V9 fmovdcc %icc */
B
blueswir1 已提交
3059
                        FMOVDCC(0);
3060
                        break;
B
blueswir1 已提交
3061
                    case 0x103: /* V9 fmovqcc %icc */
B
blueswir1 已提交
3062
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
3063
                        FMOVQCC(0);
B
blueswir1 已提交
3064
                        break;
B
blueswir1 已提交
3065
                    case 0x181: /* V9 fmovscc %xcc */
B
blueswir1 已提交
3066
                        FMOVSCC(1);
B
blueswir1 已提交
3067 3068
                        break;
                    case 0x182: /* V9 fmovdcc %xcc */
B
blueswir1 已提交
3069
                        FMOVDCC(1);
B
blueswir1 已提交
3070 3071
                        break;
                    case 0x183: /* V9 fmovqcc %xcc */
B
blueswir1 已提交
3072
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
3073
                        FMOVQCC(1);
B
blueswir1 已提交
3074
                        break;
B
blueswir1 已提交
3075 3076 3077
#undef FMOVSCC
#undef FMOVDCC
#undef FMOVQCC
B
blueswir1 已提交
3078 3079
#endif
                    case 0x51: /* fcmps, V9 %fcc */
3080 3081 3082
                        cpu_src1_32 = gen_load_fpr_F(dc, rs1);
                        cpu_src2_32 = gen_load_fpr_F(dc, rs2);
                        gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
B
blueswir1 已提交
3083
                        break;
B
blueswir1 已提交
3084
                    case 0x52: /* fcmpd, V9 %fcc */
3085 3086 3087
                        cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                        cpu_src2_64 = gen_load_fpr_D(dc, rs2);
                        gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
B
blueswir1 已提交
3088
                        break;
B
blueswir1 已提交
3089
                    case 0x53: /* fcmpq, V9 %fcc */
B
blueswir1 已提交
3090
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
3091 3092
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
3093
                        gen_op_fcmpq(rd & 3);
B
blueswir1 已提交
3094
                        break;
B
blueswir1 已提交
3095
                    case 0x55: /* fcmpes, V9 %fcc */
3096 3097 3098
                        cpu_src1_32 = gen_load_fpr_F(dc, rs1);
                        cpu_src2_32 = gen_load_fpr_F(dc, rs2);
                        gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
B
blueswir1 已提交
3099 3100
                        break;
                    case 0x56: /* fcmped, V9 %fcc */
3101 3102 3103
                        cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                        cpu_src2_64 = gen_load_fpr_D(dc, rs2);
                        gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
B
blueswir1 已提交
3104
                        break;
B
blueswir1 已提交
3105
                    case 0x57: /* fcmpeq, V9 %fcc */
B
blueswir1 已提交
3106
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
3107 3108
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
3109
                        gen_op_fcmpeq(rd & 3);
B
blueswir1 已提交
3110
                        break;
B
blueswir1 已提交
3111 3112 3113 3114 3115
                    default:
                        goto illegal_insn;
                }
            } else if (xop == 0x2) {
                // clr/mov shortcut
B
bellard 已提交
3116 3117

                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
3118
                if (rs1 == 0) {
B
blueswir1 已提交
3119
                    // or %g0, x, y -> mov T0, x; mov y, T0
B
blueswir1 已提交
3120
                    if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
3121 3122
                        TCGv r_const;

B
Blue Swirl 已提交
3123 3124
                        simm = GET_FIELDs(insn, 19, 31);
                        r_const = tcg_const_tl(simm);
B
blueswir1 已提交
3125 3126
                        gen_movl_TN_reg(rd, r_const);
                        tcg_temp_free(r_const);
B
blueswir1 已提交
3127 3128
                    } else {            /* register */
                        rs2 = GET_FIELD(insn, 27, 31);
3129
                        gen_movl_reg_TN(rs2, cpu_dst);
B
blueswir1 已提交
3130
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3131 3132
                    }
                } else {
3133
                    cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
3134
                    if (IS_IMM) {       /* immediate */
B
Blue Swirl 已提交
3135 3136
                        simm = GET_FIELDs(insn, 19, 31);
                        tcg_gen_ori_tl(cpu_dst, cpu_src1, simm);
B
blueswir1 已提交
3137
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3138 3139 3140 3141
                    } else {            /* register */
                        // or x, %g0, y -> mov T1, x; mov y, T1
                        rs2 = GET_FIELD(insn, 27, 31);
                        if (rs2 != 0) {
3142 3143
                            gen_movl_reg_TN(rs2, cpu_src2);
                            tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
B
blueswir1 已提交
3144
                            gen_movl_TN_reg(rd, cpu_dst);
3145
                        } else
B
blueswir1 已提交
3146
                            gen_movl_TN_reg(rd, cpu_src1);
B
blueswir1 已提交
3147 3148
                    }
                }
B
bellard 已提交
3149
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3150
            } else if (xop == 0x25) { /* sll, V9 sllx */
3151
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
3152
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
3153
                    simm = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
3154
                    if (insn & (1 << 12)) {
B
Blue Swirl 已提交
3155
                        tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
B
blueswir1 已提交
3156
                    } else {
B
Blue Swirl 已提交
3157
                        tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
B
blueswir1 已提交
3158
                    }
B
blueswir1 已提交
3159
                } else {                /* register */
B
bellard 已提交
3160
                    rs2 = GET_FIELD(insn, 27, 31);
3161
                    gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
3162
                    if (insn & (1 << 12)) {
3163
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
B
blueswir1 已提交
3164
                    } else {
3165
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
B
blueswir1 已提交
3166
                    }
B
blueswir1 已提交
3167
                    tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
B
bellard 已提交
3168
                }
3169
                gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3170
            } else if (xop == 0x26) { /* srl, V9 srlx */
3171
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
3172
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
3173
                    simm = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
3174
                    if (insn & (1 << 12)) {
B
Blue Swirl 已提交
3175
                        tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
B
blueswir1 已提交
3176
                    } else {
3177
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
B
Blue Swirl 已提交
3178
                        tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
B
blueswir1 已提交
3179
                    }
B
blueswir1 已提交
3180
                } else {                /* register */
B
bellard 已提交
3181
                    rs2 = GET_FIELD(insn, 27, 31);
3182
                    gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
3183
                    if (insn & (1 << 12)) {
3184 3185
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
                        tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
B
blueswir1 已提交
3186
                    } else {
3187 3188 3189
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
                        tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
B
blueswir1 已提交
3190
                    }
B
bellard 已提交
3191
                }
3192
                gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3193
            } else if (xop == 0x27) { /* sra, V9 srax */
3194
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
3195
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
3196
                    simm = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
3197
                    if (insn & (1 << 12)) {
B
Blue Swirl 已提交
3198
                        tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
B
blueswir1 已提交
3199
                    } else {
3200
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
B
blueswir1 已提交
3201
                        tcg_gen_ext32s_i64(cpu_dst, cpu_dst);
B
Blue Swirl 已提交
3202
                        tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
B
blueswir1 已提交
3203
                    }
B
blueswir1 已提交
3204
                } else {                /* register */
B
bellard 已提交
3205
                    rs2 = GET_FIELD(insn, 27, 31);
3206
                    gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
3207
                    if (insn & (1 << 12)) {
3208 3209
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
                        tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
B
blueswir1 已提交
3210
                    } else {
3211 3212
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
B
blueswir1 已提交
3213
                        tcg_gen_ext32s_i64(cpu_dst, cpu_dst);
3214
                        tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
B
blueswir1 已提交
3215
                    }
B
bellard 已提交
3216
                }
3217
                gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
3218
#endif
3219
            } else if (xop < 0x36) {
3220
                if (xop < 0x20) {
3221 3222
                    cpu_src1 = get_src1(insn, cpu_src1);
                    cpu_src2 = get_src2(insn, cpu_src2);
3223
                    switch (xop & ~0x10) {
3224
                    case 0x0: /* add */
3225 3226 3227 3228
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            if (xop & 0x10) {
                                gen_op_addi_cc(cpu_dst, cpu_src1, simm);
B
Blue Swirl 已提交
3229 3230
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
                                dc->cc_op = CC_OP_ADD;
3231 3232 3233 3234 3235 3236
                            } else {
                                tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
                            }
                        } else {
                            if (xop & 0x10) {
                                gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
B
Blue Swirl 已提交
3237 3238
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
                                dc->cc_op = CC_OP_ADD;
3239 3240 3241 3242
                            } else {
                                tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
                            }
                        }
3243
                        break;
3244
                    case 0x1: /* and */
3245 3246 3247 3248 3249 3250 3251
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_andi_tl(cpu_dst, cpu_src1, simm);
                        } else {
                            tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2);
                        }
                        if (xop & 0x10) {
3252 3253 3254
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3255
                        }
3256
                        break;
3257
                    case 0x2: /* or */
3258 3259 3260 3261 3262 3263
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_ori_tl(cpu_dst, cpu_src1, simm);
                        } else {
                            tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
                        }
3264
                        if (xop & 0x10) {
3265 3266 3267
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3268
                        }
B
blueswir1 已提交
3269
                        break;
3270
                    case 0x3: /* xor */
3271 3272 3273 3274 3275 3276
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_xori_tl(cpu_dst, cpu_src1, simm);
                        } else {
                            tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
                        }
3277
                        if (xop & 0x10) {
3278 3279 3280
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3281
                        }
3282
                        break;
3283
                    case 0x4: /* sub */
3284 3285 3286
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            if (xop & 0x10) {
B
Blue Swirl 已提交
3287
                                gen_op_subi_cc(cpu_dst, cpu_src1, simm, dc);
3288 3289 3290 3291 3292 3293
                            } else {
                                tcg_gen_subi_tl(cpu_dst, cpu_src1, simm);
                            }
                        } else {
                            if (xop & 0x10) {
                                gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
B
Blue Swirl 已提交
3294 3295
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
                                dc->cc_op = CC_OP_SUB;
3296 3297 3298 3299
                            } else {
                                tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
                            }
                        }
3300
                        break;
3301
                    case 0x5: /* andn */
3302 3303 3304 3305 3306 3307
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_andi_tl(cpu_dst, cpu_src1, ~simm);
                        } else {
                            tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2);
                        }
3308
                        if (xop & 0x10) {
3309 3310 3311
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3312
                        }
3313
                        break;
3314
                    case 0x6: /* orn */
3315 3316 3317 3318 3319 3320
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_ori_tl(cpu_dst, cpu_src1, ~simm);
                        } else {
                            tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2);
                        }
3321
                        if (xop & 0x10) {
3322 3323 3324
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3325
                        }
3326
                        break;
3327
                    case 0x7: /* xorn */
3328 3329 3330 3331 3332 3333 3334
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_xori_tl(cpu_dst, cpu_src1, ~simm);
                        } else {
                            tcg_gen_not_tl(cpu_tmp0, cpu_src2);
                            tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3335
                        if (xop & 0x10) {
3336 3337 3338
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3339
                        }
3340
                        break;
3341
                    case 0x8: /* addx, V9 addc */
3342 3343
                        gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
                                        (xop & 0x10));
3344
                        break;
P
pbrook 已提交
3345
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3346
                    case 0x9: /* V9 mulx */
3347 3348 3349 3350 3351 3352
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            tcg_gen_muli_i64(cpu_dst, cpu_src1, simm);
                        } else {
                            tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2);
                        }
P
pbrook 已提交
3353 3354
                        break;
#endif
3355
                    case 0xa: /* umul */
B
blueswir1 已提交
3356
                        CHECK_IU_FEATURE(dc, MUL);
3357
                        gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
3358
                        if (xop & 0x10) {
3359 3360 3361
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3362
                        }
3363
                        break;
3364
                    case 0xb: /* smul */
B
blueswir1 已提交
3365
                        CHECK_IU_FEATURE(dc, MUL);
3366
                        gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
3367
                        if (xop & 0x10) {
3368 3369 3370
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
                            dc->cc_op = CC_OP_LOGIC;
3371
                        }
3372
                        break;
3373
                    case 0xc: /* subx, V9 subc */
3374 3375
                        gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
                                        (xop & 0x10));
3376
                        break;
P
pbrook 已提交
3377
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3378
                    case 0xd: /* V9 udivx */
3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389
                        {
                            TCGv r_temp1, r_temp2;
                            r_temp1 = tcg_temp_local_new();
                            r_temp2 = tcg_temp_local_new();
                            tcg_gen_mov_tl(r_temp1, cpu_src1);
                            tcg_gen_mov_tl(r_temp2, cpu_src2);
                            gen_trap_ifdivzero_tl(r_temp2);
                            tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2);
                            tcg_temp_free(r_temp1);
                            tcg_temp_free(r_temp2);
                        }
P
pbrook 已提交
3390 3391
                        break;
#endif
3392
                    case 0xe: /* udiv */
B
blueswir1 已提交
3393
                        CHECK_IU_FEATURE(dc, DIV);
3394
                        if (xop & 0x10) {
3395 3396
                            gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
                                               cpu_src2);
B
Blue Swirl 已提交
3397
                            dc->cc_op = CC_OP_DIV;
3398
                        } else {
3399 3400
                            gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
                                            cpu_src2);
3401
                        }
3402
                        break;
3403
                    case 0xf: /* sdiv */
B
blueswir1 已提交
3404
                        CHECK_IU_FEATURE(dc, DIV);
3405
                        if (xop & 0x10) {
3406 3407
                            gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
                                               cpu_src2);
B
Blue Swirl 已提交
3408
                            dc->cc_op = CC_OP_DIV;
3409
                        } else {
3410 3411
                            gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
                                            cpu_src2);
3412
                        }
3413 3414 3415 3416
                        break;
                    default:
                        goto illegal_insn;
                    }
3417
                    gen_movl_TN_reg(rd, cpu_dst);
3418
                } else {
3419 3420
                    cpu_src1 = get_src1(insn, cpu_src1);
                    cpu_src2 = get_src2(insn, cpu_src2);
3421
                    switch (xop) {
B
blueswir1 已提交
3422
                    case 0x20: /* taddcc */
3423 3424
                        gen_op_tadd_cc(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3425 3426
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
                        dc->cc_op = CC_OP_TADD;
B
blueswir1 已提交
3427 3428
                        break;
                    case 0x21: /* tsubcc */
3429 3430
                        gen_op_tsub_cc(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3431 3432
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
                        dc->cc_op = CC_OP_TSUB;
B
blueswir1 已提交
3433 3434
                        break;
                    case 0x22: /* taddcctv */
3435 3436 3437
                        save_state(dc, cpu_cond);
                        gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3438 3439
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV);
                        dc->cc_op = CC_OP_TADDTV;
B
blueswir1 已提交
3440 3441
                        break;
                    case 0x23: /* tsubcctv */
3442 3443 3444
                        save_state(dc, cpu_cond);
                        gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3445 3446
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV);
                        dc->cc_op = CC_OP_TSUBTV;
B
blueswir1 已提交
3447
                        break;
3448
                    case 0x24: /* mulscc */
3449
                        gen_helper_compute_psr(cpu_env);
3450 3451
                        gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3452 3453
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
                        dc->cc_op = CC_OP_ADD;
3454
                        break;
B
bellard 已提交
3455
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3456
                    case 0x25:  /* sll */
3457
                        if (IS_IMM) { /* immediate */
B
Blue Swirl 已提交
3458 3459
                            simm = GET_FIELDs(insn, 20, 31);
                            tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
3460 3461 3462 3463
                        } else { /* register */
                            tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
                            tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3464
                        gen_movl_TN_reg(rd, cpu_dst);
3465
                        break;
B
bellard 已提交
3466
                    case 0x26:  /* srl */
3467
                        if (IS_IMM) { /* immediate */
B
Blue Swirl 已提交
3468 3469
                            simm = GET_FIELDs(insn, 20, 31);
                            tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
3470 3471 3472 3473
                        } else { /* register */
                            tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
                            tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3474
                        gen_movl_TN_reg(rd, cpu_dst);
3475
                        break;
B
bellard 已提交
3476
                    case 0x27:  /* sra */
3477
                        if (IS_IMM) { /* immediate */
B
Blue Swirl 已提交
3478 3479
                            simm = GET_FIELDs(insn, 20, 31);
                            tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
3480 3481 3482 3483
                        } else { /* register */
                            tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
                            tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3484
                        gen_movl_TN_reg(rd, cpu_dst);
3485
                        break;
B
bellard 已提交
3486
#endif
3487 3488 3489
                    case 0x30:
                        {
                            switch(rd) {
B
bellard 已提交
3490
                            case 0: /* wry */
3491 3492
                                tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
                                tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
3493
                                break;
3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504
#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 已提交
3505
                            case 0x2: /* V9 wrccr */
3506
                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
3507
                                gen_helper_wrccr(cpu_env, cpu_dst);
3508 3509
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
                                dc->cc_op = CC_OP_FLAGS;
B
blueswir1 已提交
3510 3511
                                break;
                            case 0x3: /* V9 wrasi */
3512
                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
I
Igor V. Kovalenko 已提交
3513
                                tcg_gen_andi_tl(cpu_dst, cpu_dst, 0xff);
3514
                                tcg_gen_trunc_tl_i32(cpu_asi, cpu_dst);
B
blueswir1 已提交
3515 3516
                                break;
                            case 0x6: /* V9 wrfprs */
3517
                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
3518
                                tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst);
3519
                                save_state(dc, cpu_cond);
3520
                                gen_op_next_insn();
B
bellard 已提交
3521
                                tcg_gen_exit_tb(0);
3522
                                dc->is_br = 1;
B
blueswir1 已提交
3523 3524
                                break;
                            case 0xf: /* V9 sir, nop if user */
B
bellard 已提交
3525
#if !defined(CONFIG_USER_ONLY)
3526
                                if (supervisor(dc)) {
B
blueswir1 已提交
3527
                                    ; // XXX
3528
                                }
B
bellard 已提交
3529
#endif
B
blueswir1 已提交
3530 3531
                                break;
                            case 0x13: /* Graphics Status */
3532
                                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
3533
                                    goto jmp_insn;
3534
                                tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
B
blueswir1 已提交
3535
                                break;
3536 3537 3538 3539
                            case 0x14: /* Softint set */
                                if (!supervisor(dc))
                                    goto illegal_insn;
                                tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
3540
                                gen_helper_set_softint(cpu_env, cpu_tmp64);
3541 3542 3543 3544 3545
                                break;
                            case 0x15: /* Softint clear */
                                if (!supervisor(dc))
                                    goto illegal_insn;
                                tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
3546
                                gen_helper_clear_softint(cpu_env, cpu_tmp64);
3547 3548 3549 3550 3551
                                break;
                            case 0x16: /* Softint write */
                                if (!supervisor(dc))
                                    goto illegal_insn;
                                tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
3552
                                gen_helper_write_softint(cpu_env, cpu_tmp64);
3553
                                break;
B
blueswir1 已提交
3554
                            case 0x17: /* Tick compare */
B
bellard 已提交
3555
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3556 3557
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
3558
#endif
B
blueswir1 已提交
3559
                                {
P
pbrook 已提交
3560
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3561

3562
                                    tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
3563
                                                   cpu_src2);
P
pbrook 已提交
3564
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3565 3566
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, tick));
P
pbrook 已提交
3567 3568 3569
                                    gen_helper_tick_set_limit(r_tickptr,
                                                              cpu_tick_cmpr);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3570
                                }
B
blueswir1 已提交
3571 3572
                                break;
                            case 0x18: /* System tick */
B
bellard 已提交
3573
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3574 3575
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
3576
#endif
B
blueswir1 已提交
3577
                                {
P
pbrook 已提交
3578
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3579

3580 3581
                                    tcg_gen_xor_tl(cpu_dst, cpu_src1,
                                                   cpu_src2);
P
pbrook 已提交
3582
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3583 3584
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, stick));
P
pbrook 已提交
3585 3586 3587
                                    gen_helper_tick_set_count(r_tickptr,
                                                              cpu_dst);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3588
                                }
B
blueswir1 已提交
3589 3590
                                break;
                            case 0x19: /* System tick compare */
B
bellard 已提交
3591
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3592 3593
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
3594
#endif
B
blueswir1 已提交
3595
                                {
P
pbrook 已提交
3596
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3597

3598
                                    tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
3599
                                                   cpu_src2);
P
pbrook 已提交
3600
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3601 3602
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, stick));
P
pbrook 已提交
3603 3604 3605
                                    gen_helper_tick_set_limit(r_tickptr,
                                                              cpu_stick_cmpr);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3606
                                }
B
blueswir1 已提交
3607
                                break;
B
bellard 已提交
3608

B
blueswir1 已提交
3609
                            case 0x10: /* Performance Control */
B
blueswir1 已提交
3610 3611
                            case 0x11: /* Performance Instrumentation
                                          Counter */
B
blueswir1 已提交
3612
                            case 0x12: /* Dispatch Control */
B
bellard 已提交
3613
#endif
B
bellard 已提交
3614
                            default:
3615 3616 3617 3618
                                goto illegal_insn;
                            }
                        }
                        break;
3619
#if !defined(CONFIG_USER_ONLY)
3620
                    case 0x31: /* wrpsr, V9 saved, restored */
3621
                        {
B
blueswir1 已提交
3622 3623
                            if (!supervisor(dc))
                                goto priv_insn;
B
bellard 已提交
3624
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3625 3626
                            switch (rd) {
                            case 0:
3627
                                gen_helper_saved(cpu_env);
B
blueswir1 已提交
3628 3629
                                break;
                            case 1:
3630
                                gen_helper_restored(cpu_env);
B
blueswir1 已提交
3631
                                break;
B
blueswir1 已提交
3632 3633 3634 3635 3636
                            case 2: /* UA2005 allclean */
                            case 3: /* UA2005 otherw */
                            case 4: /* UA2005 normalw */
                            case 5: /* UA2005 invalw */
                                // XXX
B
blueswir1 已提交
3637
                            default:
B
bellard 已提交
3638 3639 3640
                                goto illegal_insn;
                            }
#else
3641
                            tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
3642
                            gen_helper_wrpsr(cpu_env, cpu_dst);
3643 3644
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
                            dc->cc_op = CC_OP_FLAGS;
3645
                            save_state(dc, cpu_cond);
B
bellard 已提交
3646
                            gen_op_next_insn();
B
bellard 已提交
3647
                            tcg_gen_exit_tb(0);
B
blueswir1 已提交
3648
                            dc->is_br = 1;
B
bellard 已提交
3649
#endif
3650 3651
                        }
                        break;
3652
                    case 0x32: /* wrwim, V9 wrpr */
3653
                        {
B
blueswir1 已提交
3654 3655
                            if (!supervisor(dc))
                                goto priv_insn;
3656
                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
B
bellard 已提交
3657
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3658 3659
                            switch (rd) {
                            case 0: // tpc
3660
                                {
P
pbrook 已提交
3661
                                    TCGv_ptr r_tsptr;
3662

P
pbrook 已提交
3663
                                    r_tsptr = tcg_temp_new_ptr();
3664
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3665
                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
3666
                                                  offsetof(trap_state, tpc));
P
pbrook 已提交
3667
                                    tcg_temp_free_ptr(r_tsptr);
3668
                                }
B
blueswir1 已提交
3669 3670
                                break;
                            case 1: // tnpc
3671
                                {
P
pbrook 已提交
3672
                                    TCGv_ptr r_tsptr;
3673

P
pbrook 已提交
3674
                                    r_tsptr = tcg_temp_new_ptr();
3675
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3676
                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
3677
                                                  offsetof(trap_state, tnpc));
P
pbrook 已提交
3678
                                    tcg_temp_free_ptr(r_tsptr);
3679
                                }
B
blueswir1 已提交
3680 3681
                                break;
                            case 2: // tstate
3682
                                {
P
pbrook 已提交
3683
                                    TCGv_ptr r_tsptr;
3684

P
pbrook 已提交
3685
                                    r_tsptr = tcg_temp_new_ptr();
3686
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3687
                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
B
blueswir1 已提交
3688 3689
                                                  offsetof(trap_state,
                                                           tstate));
P
pbrook 已提交
3690
                                    tcg_temp_free_ptr(r_tsptr);
3691
                                }
B
blueswir1 已提交
3692 3693
                                break;
                            case 3: // tt
3694
                                {
P
pbrook 已提交
3695
                                    TCGv_ptr r_tsptr;
3696

P
pbrook 已提交
3697
                                    r_tsptr = tcg_temp_new_ptr();
3698
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
B
blueswir1 已提交
3699 3700
                                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                    tcg_gen_st_i32(cpu_tmp32, r_tsptr,
3701
                                                   offsetof(trap_state, tt));
P
pbrook 已提交
3702
                                    tcg_temp_free_ptr(r_tsptr);
3703
                                }
B
blueswir1 已提交
3704 3705
                                break;
                            case 4: // tick
B
blueswir1 已提交
3706
                                {
P
pbrook 已提交
3707
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3708

P
pbrook 已提交
3709
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3710 3711
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, tick));
P
pbrook 已提交
3712 3713 3714
                                    gen_helper_tick_set_count(r_tickptr,
                                                              cpu_tmp0);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3715
                                }
B
blueswir1 已提交
3716 3717
                                break;
                            case 5: // tba
3718
                                tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
B
blueswir1 已提交
3719 3720
                                break;
                            case 6: // pstate
3721 3722 3723 3724 3725
                                {
                                    TCGv r_tmp = tcg_temp_local_new();

                                    tcg_gen_mov_tl(r_tmp, cpu_tmp0);
                                    save_state(dc, cpu_cond);
3726
                                    gen_helper_wrpstate(cpu_env, r_tmp);
3727 3728 3729
                                    tcg_temp_free(r_tmp);
                                    dc->npc = DYNAMIC_PC;
                                }
B
blueswir1 已提交
3730 3731
                                break;
                            case 7: // tl
3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742
                                {
                                    TCGv r_tmp = tcg_temp_local_new();

                                    tcg_gen_mov_tl(r_tmp, cpu_tmp0);
                                    save_state(dc, cpu_cond);
                                    tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp);
                                    tcg_temp_free(r_tmp);
                                    tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                   offsetof(CPUSPARCState, tl));
                                    dc->npc = DYNAMIC_PC;
                                }
B
blueswir1 已提交
3743 3744
                                break;
                            case 8: // pil
3745
                                gen_helper_wrpil(cpu_env, cpu_tmp0);
B
blueswir1 已提交
3746 3747
                                break;
                            case 9: // cwp
3748
                                gen_helper_wrcwp(cpu_env, cpu_tmp0);
B
blueswir1 已提交
3749 3750
                                break;
                            case 10: // cansave
3751
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3752 3753 3754
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        cansave));
B
blueswir1 已提交
3755 3756
                                break;
                            case 11: // canrestore
3757
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3758 3759 3760
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        canrestore));
B
blueswir1 已提交
3761 3762
                                break;
                            case 12: // cleanwin
3763
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3764 3765 3766
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        cleanwin));
B
blueswir1 已提交
3767 3768
                                break;
                            case 13: // otherwin
3769
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3770 3771 3772
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        otherwin));
B
blueswir1 已提交
3773 3774
                                break;
                            case 14: // wstate
3775
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3776 3777 3778
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        wstate));
B
blueswir1 已提交
3779
                                break;
B
blueswir1 已提交
3780
                            case 16: // UA2005 gl
3781
                                CHECK_IU_FEATURE(dc, GL);
3782
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3783 3784
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState, gl));
B
blueswir1 已提交
3785 3786
                                break;
                            case 26: // UA2005 strand status
3787
                                CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
3788 3789
                                if (!hypervisor(dc))
                                    goto priv_insn;
B
blueswir1 已提交
3790
                                tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
B
blueswir1 已提交
3791
                                break;
B
blueswir1 已提交
3792 3793 3794
                            default:
                                goto illegal_insn;
                            }
B
bellard 已提交
3795
#else
3796
                            tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3797 3798 3799
                            if (dc->def->nwindows != 32)
                                tcg_gen_andi_tl(cpu_tmp32, cpu_tmp32,
                                                (1 << dc->def->nwindows) - 1);
3800
                            tcg_gen_mov_i32(cpu_wim, cpu_tmp32);
B
bellard 已提交
3801
#endif
3802 3803
                        }
                        break;
B
blueswir1 已提交
3804
                    case 0x33: /* wrtbr, UA2005 wrhpr */
3805
                        {
B
blueswir1 已提交
3806
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3807 3808
                            if (!supervisor(dc))
                                goto priv_insn;
3809
                            tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
B
blueswir1 已提交
3810
#else
3811
                            CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
3812 3813
                            if (!hypervisor(dc))
                                goto priv_insn;
3814
                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
B
blueswir1 已提交
3815 3816 3817
                            switch (rd) {
                            case 0: // hpstate
                                // XXX gen_op_wrhpstate();
3818
                                save_state(dc, cpu_cond);
B
blueswir1 已提交
3819
                                gen_op_next_insn();
B
bellard 已提交
3820
                                tcg_gen_exit_tb(0);
B
blueswir1 已提交
3821 3822 3823 3824 3825 3826
                                dc->is_br = 1;
                                break;
                            case 1: // htstate
                                // XXX gen_op_wrhtstate();
                                break;
                            case 3: // hintp
3827
                                tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
B
blueswir1 已提交
3828 3829
                                break;
                            case 5: // htba
3830
                                tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
B
blueswir1 已提交
3831 3832
                                break;
                            case 31: // hstick_cmpr
B
blueswir1 已提交
3833
                                {
P
pbrook 已提交
3834
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3835

3836
                                    tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
P
pbrook 已提交
3837
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3838 3839
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, hstick));
P
pbrook 已提交
3840 3841 3842
                                    gen_helper_tick_set_limit(r_tickptr,
                                                              cpu_hstick_cmpr);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3843
                                }
B
blueswir1 已提交
3844 3845 3846 3847 3848 3849
                                break;
                            case 6: // hver readonly
                            default:
                                goto illegal_insn;
                            }
#endif
3850 3851 3852
                        }
                        break;
#endif
B
bellard 已提交
3853
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3854 3855 3856 3857
                    case 0x2c: /* V9 movcc */
                        {
                            int cc = GET_FIELD_SP(insn, 11, 12);
                            int cond = GET_FIELD_SP(insn, 14, 17);
B
blueswir1 已提交
3858
                            TCGv r_cond;
3859 3860
                            int l1;

P
pbrook 已提交
3861
                            r_cond = tcg_temp_new();
B
blueswir1 已提交
3862 3863
                            if (insn & (1 << 18)) {
                                if (cc == 0)
3864
                                    gen_cond(r_cond, 0, cond, dc);
B
blueswir1 已提交
3865
                                else if (cc == 2)
3866
                                    gen_cond(r_cond, 1, cond, dc);
B
blueswir1 已提交
3867 3868 3869
                                else
                                    goto illegal_insn;
                            } else {
B
blueswir1 已提交
3870
                                gen_fcond(r_cond, cc, cond);
B
blueswir1 已提交
3871
                            }
3872 3873 3874

                            l1 = gen_new_label();

P
pbrook 已提交
3875
                            tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
3876
                            if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
3877 3878
                                TCGv r_const;

B
Blue Swirl 已提交
3879 3880
                                simm = GET_FIELD_SPs(insn, 0, 10);
                                r_const = tcg_const_tl(simm);
B
blueswir1 已提交
3881 3882
                                gen_movl_TN_reg(rd, r_const);
                                tcg_temp_free(r_const);
3883 3884
                            } else {
                                rs2 = GET_FIELD_SP(insn, 0, 4);
B
blueswir1 已提交
3885 3886
                                gen_movl_reg_TN(rs2, cpu_tmp0);
                                gen_movl_TN_reg(rd, cpu_tmp0);
3887 3888
                            }
                            gen_set_label(l1);
B
blueswir1 已提交
3889
                            tcg_temp_free(r_cond);
B
blueswir1 已提交
3890 3891 3892
                            break;
                        }
                    case 0x2d: /* V9 sdivx */
3893 3894
                        gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3895 3896 3897
                        break;
                    case 0x2e: /* V9 popc */
                        {
B
blueswir1 已提交
3898
                            cpu_src2 = get_src2(insn, cpu_src2);
P
pbrook 已提交
3899
                            gen_helper_popc(cpu_dst, cpu_src2);
3900
                            gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3901 3902 3903 3904
                        }
                    case 0x2f: /* V9 movr */
                        {
                            int cond = GET_FIELD_SP(insn, 10, 12);
3905 3906
                            int l1;

3907
                            cpu_src1 = get_src1(insn, cpu_src1);
3908 3909 3910

                            l1 = gen_new_label();

P
pbrook 已提交
3911 3912
                            tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond],
                                              cpu_src1, 0, l1);
B
blueswir1 已提交
3913
                            if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
3914 3915
                                TCGv r_const;

B
Blue Swirl 已提交
3916 3917
                                simm = GET_FIELD_SPs(insn, 0, 9);
                                r_const = tcg_const_tl(simm);
B
blueswir1 已提交
3918 3919
                                gen_movl_TN_reg(rd, r_const);
                                tcg_temp_free(r_const);
3920
                            } else {
B
blueswir1 已提交
3921
                                rs2 = GET_FIELD_SP(insn, 0, 4);
B
blueswir1 已提交
3922 3923
                                gen_movl_reg_TN(rs2, cpu_tmp0);
                                gen_movl_TN_reg(rd, cpu_tmp0);
B
blueswir1 已提交
3924
                            }
3925
                            gen_set_label(l1);
B
blueswir1 已提交
3926 3927 3928 3929 3930 3931 3932
                            break;
                        }
#endif
                    default:
                        goto illegal_insn;
                    }
                }
3933 3934 3935 3936 3937
            } 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);
3938
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
blueswir1 已提交
3939
                    goto jmp_insn;
3940 3941

                switch (opf) {
B
blueswir1 已提交
3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956
                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 */
B
blueswir1 已提交
3957
                    CHECK_FPU_FEATURE(dc, VIS1);
3958
                    cpu_src1 = get_src1(insn, cpu_src1);
3959
                    gen_movl_reg_TN(rs2, cpu_src2);
3960
                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
3961
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3962 3963
                    break;
                case 0x012: /* VIS I array16 */
B
blueswir1 已提交
3964
                    CHECK_FPU_FEATURE(dc, VIS1);
3965
                    cpu_src1 = get_src1(insn, cpu_src1);
3966
                    gen_movl_reg_TN(rs2, cpu_src2);
3967
                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
3968 3969
                    tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3970 3971
                    break;
                case 0x014: /* VIS I array32 */
B
blueswir1 已提交
3972
                    CHECK_FPU_FEATURE(dc, VIS1);
3973
                    cpu_src1 = get_src1(insn, cpu_src1);
3974
                    gen_movl_reg_TN(rs2, cpu_src2);
3975
                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
3976 3977
                    tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3978
                    break;
3979
                case 0x018: /* VIS I alignaddr */
B
blueswir1 已提交
3980
                    CHECK_FPU_FEATURE(dc, VIS1);
3981
                    cpu_src1 = get_src1(insn, cpu_src1);
3982
                    gen_movl_reg_TN(rs2, cpu_src2);
3983
                    gen_helper_alignaddr(cpu_dst, cpu_env, cpu_src1, cpu_src2);
3984
                    gen_movl_TN_reg(rd, cpu_dst);
3985
                    break;
B
blueswir1 已提交
3986
                case 0x019: /* VIS II bmask */
3987 3988
                case 0x01a: /* VIS I alignaddrl */
                    // XXX
B
blueswir1 已提交
3989 3990
                    goto illegal_insn;
                case 0x020: /* VIS I fcmple16 */
B
blueswir1 已提交
3991
                    CHECK_FPU_FEATURE(dc, VIS1);
3992 3993
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3994
                    gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
3995
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3996 3997
                    break;
                case 0x022: /* VIS I fcmpne16 */
B
blueswir1 已提交
3998
                    CHECK_FPU_FEATURE(dc, VIS1);
3999 4000
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4001
                    gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
4002
                    gen_movl_TN_reg(rd, cpu_dst);
4003
                    break;
B
blueswir1 已提交
4004
                case 0x024: /* VIS I fcmple32 */
B
blueswir1 已提交
4005
                    CHECK_FPU_FEATURE(dc, VIS1);
4006 4007
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4008
                    gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
4009
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4010 4011
                    break;
                case 0x026: /* VIS I fcmpne32 */
B
blueswir1 已提交
4012
                    CHECK_FPU_FEATURE(dc, VIS1);
4013 4014
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4015
                    gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
4016
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4017 4018
                    break;
                case 0x028: /* VIS I fcmpgt16 */
B
blueswir1 已提交
4019
                    CHECK_FPU_FEATURE(dc, VIS1);
4020 4021
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4022
                    gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
4023
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4024 4025
                    break;
                case 0x02a: /* VIS I fcmpeq16 */
B
blueswir1 已提交
4026
                    CHECK_FPU_FEATURE(dc, VIS1);
4027 4028
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4029
                    gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
4030
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4031 4032
                    break;
                case 0x02c: /* VIS I fcmpgt32 */
B
blueswir1 已提交
4033
                    CHECK_FPU_FEATURE(dc, VIS1);
4034 4035
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4036
                    gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
4037
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4038 4039
                    break;
                case 0x02e: /* VIS I fcmpeq32 */
B
blueswir1 已提交
4040
                    CHECK_FPU_FEATURE(dc, VIS1);
4041 4042
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4043
                    gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
4044
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4045 4046
                    break;
                case 0x031: /* VIS I fmul8x16 */
B
blueswir1 已提交
4047
                    CHECK_FPU_FEATURE(dc, VIS1);
4048
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
B
blueswir1 已提交
4049 4050
                    break;
                case 0x033: /* VIS I fmul8x16au */
B
blueswir1 已提交
4051
                    CHECK_FPU_FEATURE(dc, VIS1);
4052
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
B
blueswir1 已提交
4053 4054
                    break;
                case 0x035: /* VIS I fmul8x16al */
B
blueswir1 已提交
4055
                    CHECK_FPU_FEATURE(dc, VIS1);
4056
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
B
blueswir1 已提交
4057 4058
                    break;
                case 0x036: /* VIS I fmul8sux16 */
B
blueswir1 已提交
4059
                    CHECK_FPU_FEATURE(dc, VIS1);
4060
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
B
blueswir1 已提交
4061 4062
                    break;
                case 0x037: /* VIS I fmul8ulx16 */
B
blueswir1 已提交
4063
                    CHECK_FPU_FEATURE(dc, VIS1);
4064
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
B
blueswir1 已提交
4065 4066
                    break;
                case 0x038: /* VIS I fmuld8sux16 */
B
blueswir1 已提交
4067
                    CHECK_FPU_FEATURE(dc, VIS1);
4068
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
B
blueswir1 已提交
4069 4070
                    break;
                case 0x039: /* VIS I fmuld8ulx16 */
B
blueswir1 已提交
4071
                    CHECK_FPU_FEATURE(dc, VIS1);
4072
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
B
blueswir1 已提交
4073 4074 4075 4076 4077
                    break;
                case 0x03a: /* VIS I fpack32 */
                case 0x03b: /* VIS I fpack16 */
                case 0x03d: /* VIS I fpackfix */
                    goto illegal_insn;
R
Richard Henderson 已提交
4078 4079 4080 4081
                case 0x03e: /* VIS I pdist */
                    CHECK_FPU_FEATURE(dc, VIS1);
                    gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
                    break;
4082
                case 0x048: /* VIS I faligndata */
B
blueswir1 已提交
4083
                    CHECK_FPU_FEATURE(dc, VIS1);
4084 4085 4086 4087 4088 4089
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    cpu_src2_64 = gen_load_fpr_D(dc, rs2);
                    cpu_dst_64 = gen_dest_fpr_D();
                    gen_helper_faligndata(cpu_dst_64, cpu_env,
                                          cpu_src1_64, cpu_src2_64);
                    gen_store_fpr_D(dc, rd, cpu_dst_64);
4090
                    break;
B
blueswir1 已提交
4091
                case 0x04b: /* VIS I fpmerge */
B
blueswir1 已提交
4092
                    CHECK_FPU_FEATURE(dc, VIS1);
4093
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
B
blueswir1 已提交
4094 4095 4096 4097 4098
                    break;
                case 0x04c: /* VIS II bshuffle */
                    // XXX
                    goto illegal_insn;
                case 0x04d: /* VIS I fexpand */
B
blueswir1 已提交
4099
                    CHECK_FPU_FEATURE(dc, VIS1);
4100
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
B
blueswir1 已提交
4101 4102
                    break;
                case 0x050: /* VIS I fpadd16 */
B
blueswir1 已提交
4103
                    CHECK_FPU_FEATURE(dc, VIS1);
4104
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
B
blueswir1 已提交
4105 4106
                    break;
                case 0x051: /* VIS I fpadd16s */
B
blueswir1 已提交
4107
                    CHECK_FPU_FEATURE(dc, VIS1);
4108
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
B
blueswir1 已提交
4109 4110
                    break;
                case 0x052: /* VIS I fpadd32 */
B
blueswir1 已提交
4111
                    CHECK_FPU_FEATURE(dc, VIS1);
4112
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
B
blueswir1 已提交
4113 4114
                    break;
                case 0x053: /* VIS I fpadd32s */
B
blueswir1 已提交
4115
                    CHECK_FPU_FEATURE(dc, VIS1);
4116
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
B
blueswir1 已提交
4117 4118
                    break;
                case 0x054: /* VIS I fpsub16 */
B
blueswir1 已提交
4119
                    CHECK_FPU_FEATURE(dc, VIS1);
4120
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
B
blueswir1 已提交
4121 4122
                    break;
                case 0x055: /* VIS I fpsub16s */
B
blueswir1 已提交
4123
                    CHECK_FPU_FEATURE(dc, VIS1);
4124
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
B
blueswir1 已提交
4125 4126
                    break;
                case 0x056: /* VIS I fpsub32 */
B
blueswir1 已提交
4127
                    CHECK_FPU_FEATURE(dc, VIS1);
4128
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
B
blueswir1 已提交
4129 4130
                    break;
                case 0x057: /* VIS I fpsub32s */
B
blueswir1 已提交
4131
                    CHECK_FPU_FEATURE(dc, VIS1);
4132
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
B
blueswir1 已提交
4133
                    break;
4134
                case 0x060: /* VIS I fzero */
B
blueswir1 已提交
4135
                    CHECK_FPU_FEATURE(dc, VIS1);
4136 4137 4138
                    cpu_dst_64 = gen_dest_fpr_D();
                    tcg_gen_movi_i64(cpu_dst_64, 0);
                    gen_store_fpr_D(dc, rd, cpu_dst_64);
4139 4140
                    break;
                case 0x061: /* VIS I fzeros */
B
blueswir1 已提交
4141
                    CHECK_FPU_FEATURE(dc, VIS1);
4142 4143 4144
                    cpu_dst_32 = gen_dest_fpr_F();
                    tcg_gen_movi_i32(cpu_dst_32, 0);
                    gen_store_fpr_F(dc, rd, cpu_dst_32);
4145
                    break;
B
blueswir1 已提交
4146
                case 0x062: /* VIS I fnor */
B
blueswir1 已提交
4147
                    CHECK_FPU_FEATURE(dc, VIS1);
4148
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
B
blueswir1 已提交
4149 4150
                    break;
                case 0x063: /* VIS I fnors */
B
blueswir1 已提交
4151
                    CHECK_FPU_FEATURE(dc, VIS1);
4152
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
B
blueswir1 已提交
4153 4154
                    break;
                case 0x064: /* VIS I fandnot2 */
B
blueswir1 已提交
4155
                    CHECK_FPU_FEATURE(dc, VIS1);
4156
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
B
blueswir1 已提交
4157 4158
                    break;
                case 0x065: /* VIS I fandnot2s */
B
blueswir1 已提交
4159
                    CHECK_FPU_FEATURE(dc, VIS1);
4160
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
B
blueswir1 已提交
4161 4162
                    break;
                case 0x066: /* VIS I fnot2 */
B
blueswir1 已提交
4163
                    CHECK_FPU_FEATURE(dc, VIS1);
4164
                    gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
B
blueswir1 已提交
4165 4166
                    break;
                case 0x067: /* VIS I fnot2s */
B
blueswir1 已提交
4167
                    CHECK_FPU_FEATURE(dc, VIS1);
4168
                    gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
B
blueswir1 已提交
4169 4170
                    break;
                case 0x068: /* VIS I fandnot1 */
B
blueswir1 已提交
4171
                    CHECK_FPU_FEATURE(dc, VIS1);
4172
                    gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
B
blueswir1 已提交
4173 4174
                    break;
                case 0x069: /* VIS I fandnot1s */
B
blueswir1 已提交
4175
                    CHECK_FPU_FEATURE(dc, VIS1);
4176
                    gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
B
blueswir1 已提交
4177 4178
                    break;
                case 0x06a: /* VIS I fnot1 */
B
blueswir1 已提交
4179
                    CHECK_FPU_FEATURE(dc, VIS1);
4180
                    gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
B
blueswir1 已提交
4181 4182
                    break;
                case 0x06b: /* VIS I fnot1s */
B
blueswir1 已提交
4183
                    CHECK_FPU_FEATURE(dc, VIS1);
4184
                    gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
B
blueswir1 已提交
4185 4186
                    break;
                case 0x06c: /* VIS I fxor */
B
blueswir1 已提交
4187
                    CHECK_FPU_FEATURE(dc, VIS1);
4188
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
B
blueswir1 已提交
4189 4190
                    break;
                case 0x06d: /* VIS I fxors */
B
blueswir1 已提交
4191
                    CHECK_FPU_FEATURE(dc, VIS1);
4192
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
B
blueswir1 已提交
4193 4194
                    break;
                case 0x06e: /* VIS I fnand */
B
blueswir1 已提交
4195
                    CHECK_FPU_FEATURE(dc, VIS1);
4196
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
B
blueswir1 已提交
4197 4198
                    break;
                case 0x06f: /* VIS I fnands */
B
blueswir1 已提交
4199
                    CHECK_FPU_FEATURE(dc, VIS1);
4200
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
B
blueswir1 已提交
4201 4202
                    break;
                case 0x070: /* VIS I fand */
B
blueswir1 已提交
4203
                    CHECK_FPU_FEATURE(dc, VIS1);
4204
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
B
blueswir1 已提交
4205 4206
                    break;
                case 0x071: /* VIS I fands */
B
blueswir1 已提交
4207
                    CHECK_FPU_FEATURE(dc, VIS1);
4208
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
B
blueswir1 已提交
4209 4210
                    break;
                case 0x072: /* VIS I fxnor */
B
blueswir1 已提交
4211
                    CHECK_FPU_FEATURE(dc, VIS1);
4212
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
B
blueswir1 已提交
4213 4214
                    break;
                case 0x073: /* VIS I fxnors */
B
blueswir1 已提交
4215
                    CHECK_FPU_FEATURE(dc, VIS1);
4216
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
B
blueswir1 已提交
4217
                    break;
4218
                case 0x074: /* VIS I fsrc1 */
B
blueswir1 已提交
4219
                    CHECK_FPU_FEATURE(dc, VIS1);
4220 4221
                    cpu_src1_64 = gen_load_fpr_D(dc, rs1);
                    gen_store_fpr_D(dc, rd, cpu_src1_64);
4222 4223
                    break;
                case 0x075: /* VIS I fsrc1s */
B
blueswir1 已提交
4224
                    CHECK_FPU_FEATURE(dc, VIS1);
4225 4226
                    cpu_src1_32 = gen_load_fpr_F(dc, rs1);
                    gen_store_fpr_F(dc, rd, cpu_src1_32);
4227
                    break;
B
blueswir1 已提交
4228
                case 0x076: /* VIS I fornot2 */
B
blueswir1 已提交
4229
                    CHECK_FPU_FEATURE(dc, VIS1);
4230
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
B
blueswir1 已提交
4231 4232
                    break;
                case 0x077: /* VIS I fornot2s */
B
blueswir1 已提交
4233
                    CHECK_FPU_FEATURE(dc, VIS1);
4234
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
B
blueswir1 已提交
4235
                    break;
4236
                case 0x078: /* VIS I fsrc2 */
B
blueswir1 已提交
4237
                    CHECK_FPU_FEATURE(dc, VIS1);
4238 4239
                    cpu_src1_64 = gen_load_fpr_D(dc, rs2);
                    gen_store_fpr_D(dc, rd, cpu_src1_64);
4240 4241
                    break;
                case 0x079: /* VIS I fsrc2s */
B
blueswir1 已提交
4242
                    CHECK_FPU_FEATURE(dc, VIS1);
4243 4244
                    cpu_src1_32 = gen_load_fpr_F(dc, rs2);
                    gen_store_fpr_F(dc, rd, cpu_src1_32);
4245
                    break;
B
blueswir1 已提交
4246
                case 0x07a: /* VIS I fornot1 */
B
blueswir1 已提交
4247
                    CHECK_FPU_FEATURE(dc, VIS1);
4248
                    gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
B
blueswir1 已提交
4249 4250
                    break;
                case 0x07b: /* VIS I fornot1s */
B
blueswir1 已提交
4251
                    CHECK_FPU_FEATURE(dc, VIS1);
4252
                    gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
B
blueswir1 已提交
4253 4254
                    break;
                case 0x07c: /* VIS I for */
B
blueswir1 已提交
4255
                    CHECK_FPU_FEATURE(dc, VIS1);
4256
                    gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
B
blueswir1 已提交
4257 4258
                    break;
                case 0x07d: /* VIS I fors */
B
blueswir1 已提交
4259
                    CHECK_FPU_FEATURE(dc, VIS1);
4260
                    gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
B
blueswir1 已提交
4261
                    break;
4262
                case 0x07e: /* VIS I fone */
B
blueswir1 已提交
4263
                    CHECK_FPU_FEATURE(dc, VIS1);
4264 4265 4266
                    cpu_dst_64 = gen_dest_fpr_D();
                    tcg_gen_movi_i64(cpu_dst_64, -1);
                    gen_store_fpr_D(dc, rd, cpu_dst_64);
4267 4268
                    break;
                case 0x07f: /* VIS I fones */
B
blueswir1 已提交
4269
                    CHECK_FPU_FEATURE(dc, VIS1);
4270 4271 4272
                    cpu_dst_32 = gen_dest_fpr_F();
                    tcg_gen_movi_i32(cpu_dst_32, -1);
                    gen_store_fpr_F(dc, rd, cpu_dst_32);
4273
                    break;
B
blueswir1 已提交
4274 4275 4276 4277
                case 0x080: /* VIS I shutdown */
                case 0x081: /* VIS II siam */
                    // XXX
                    goto illegal_insn;
4278 4279 4280 4281
                default:
                    goto illegal_insn;
                }
#else
B
blueswir1 已提交
4282
                goto ncp_insn;
4283 4284
#endif
            } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
4285
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4286
                goto illegal_insn;
4287
#else
B
blueswir1 已提交
4288
                goto ncp_insn;
4289
#endif
B
bellard 已提交
4290
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4291
            } else if (xop == 0x39) { /* V9 return */
P
pbrook 已提交
4292
                TCGv_i32 r_const;
B
blueswir1 已提交
4293

4294
                save_state(dc, cpu_cond);
4295
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
4296
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
4297 4298
                    simm = GET_FIELDs(insn, 19, 31);
                    tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
B
blueswir1 已提交
4299
                } else {                /* register */
B
bellard 已提交
4300
                    rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
4301
                    if (rs2) {
4302 4303
                        gen_movl_reg_TN(rs2, cpu_src2);
                        tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4304 4305
                    } else
                        tcg_gen_mov_tl(cpu_dst, cpu_src1);
B
bellard 已提交
4306
                }
4307
                gen_helper_restore(cpu_env);
4308
                gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
4309
                r_const = tcg_const_i32(3);
P
pbrook 已提交
4310 4311
                gen_helper_check_align(cpu_dst, r_const);
                tcg_temp_free_i32(r_const);
4312
                tcg_gen_mov_tl(cpu_npc, cpu_dst);
B
blueswir1 已提交
4313 4314
                dc->npc = DYNAMIC_PC;
                goto jmp_insn;
B
bellard 已提交
4315
#endif
B
blueswir1 已提交
4316
            } else {
4317
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
4318
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
4319 4320
                    simm = GET_FIELDs(insn, 19, 31);
                    tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
B
blueswir1 已提交
4321
                } else {                /* register */
B
bellard 已提交
4322
                    rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
4323
                    if (rs2) {
4324 4325
                        gen_movl_reg_TN(rs2, cpu_src2);
                        tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4326 4327
                    } else
                        tcg_gen_mov_tl(cpu_dst, cpu_src1);
4328
                }
B
blueswir1 已提交
4329 4330 4331
                switch (xop) {
                case 0x38:      /* jmpl */
                    {
P
pbrook 已提交
4332 4333
                        TCGv r_pc;
                        TCGv_i32 r_const;
B
blueswir1 已提交
4334

P
pbrook 已提交
4335 4336 4337
                        r_pc = tcg_const_tl(dc->pc);
                        gen_movl_TN_reg(rd, r_pc);
                        tcg_temp_free(r_pc);
4338
                        gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
4339
                        r_const = tcg_const_i32(3);
P
pbrook 已提交
4340 4341
                        gen_helper_check_align(cpu_dst, r_const);
                        tcg_temp_free_i32(r_const);
4342
                        tcg_gen_mov_tl(cpu_npc, cpu_dst);
B
blueswir1 已提交
4343 4344 4345
                        dc->npc = DYNAMIC_PC;
                    }
                    goto jmp_insn;
B
bellard 已提交
4346
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
B
blueswir1 已提交
4347 4348
                case 0x39:      /* rett, V9 return */
                    {
P
pbrook 已提交
4349
                        TCGv_i32 r_const;
B
blueswir1 已提交
4350

B
blueswir1 已提交
4351 4352
                        if (!supervisor(dc))
                            goto priv_insn;
4353
                        gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
4354
                        r_const = tcg_const_i32(3);
P
pbrook 已提交
4355 4356
                        gen_helper_check_align(cpu_dst, r_const);
                        tcg_temp_free_i32(r_const);
4357
                        tcg_gen_mov_tl(cpu_npc, cpu_dst);
B
blueswir1 已提交
4358
                        dc->npc = DYNAMIC_PC;
4359
                        gen_helper_rett(cpu_env);
B
blueswir1 已提交
4360 4361 4362 4363
                    }
                    goto jmp_insn;
#endif
                case 0x3b: /* flush */
4364
                    if (!((dc)->def->features & CPU_FEATURE_FLUSH))
B
blueswir1 已提交
4365
                        goto unimp_flush;
4366
                    /* nop */
B
blueswir1 已提交
4367 4368
                    break;
                case 0x3c:      /* save */
4369
                    save_state(dc, cpu_cond);
4370
                    gen_helper_save(cpu_env);
4371
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4372 4373
                    break;
                case 0x3d:      /* restore */
4374
                    save_state(dc, cpu_cond);
4375
                    gen_helper_restore(cpu_env);
4376
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4377
                    break;
B
bellard 已提交
4378
#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
B
blueswir1 已提交
4379 4380 4381 4382 4383 4384 4385 4386
                case 0x3e:      /* V9 done/retry */
                    {
                        switch (rd) {
                        case 0:
                            if (!supervisor(dc))
                                goto priv_insn;
                            dc->npc = DYNAMIC_PC;
                            dc->pc = DYNAMIC_PC;
4387
                            gen_helper_done(cpu_env);
B
blueswir1 已提交
4388 4389 4390 4391 4392 4393
                            goto jmp_insn;
                        case 1:
                            if (!supervisor(dc))
                                goto priv_insn;
                            dc->npc = DYNAMIC_PC;
                            dc->pc = DYNAMIC_PC;
4394
                            gen_helper_retry(cpu_env);
B
blueswir1 已提交
4395 4396 4397 4398 4399 4400 4401 4402 4403 4404
                            goto jmp_insn;
                        default:
                            goto illegal_insn;
                        }
                    }
                    break;
#endif
                default:
                    goto illegal_insn;
                }
4405
            }
B
blueswir1 已提交
4406 4407 4408 4409 4410 4411
            break;
        }
        break;
    case 3:                     /* load/store instructions */
        {
            unsigned int xop = GET_FIELD(insn, 7, 12);
4412

4413 4414 4415 4416
            /* flush pending conditional evaluations before exposing
               cpu state */
            if (dc->cc_op != CC_OP_FLAGS) {
                dc->cc_op = CC_OP_FLAGS;
4417
                gen_helper_compute_psr(cpu_env);
4418
            }
4419
            cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
4420
            if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
4421
                rs2 = GET_FIELD(insn, 27, 31);
4422
                gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
4423 4424
                tcg_gen_mov_tl(cpu_addr, cpu_src1);
            } else if (IS_IMM) {     /* immediate */
B
Blue Swirl 已提交
4425 4426
                simm = GET_FIELDs(insn, 19, 31);
                tcg_gen_addi_tl(cpu_addr, cpu_src1, simm);
B
blueswir1 已提交
4427 4428 4429
            } else {            /* register */
                rs2 = GET_FIELD(insn, 27, 31);
                if (rs2 != 0) {
4430 4431
                    gen_movl_reg_TN(rs2, cpu_src2);
                    tcg_gen_add_tl(cpu_addr, cpu_src1, cpu_src2);
4432 4433
                } else
                    tcg_gen_mov_tl(cpu_addr, cpu_src1);
B
blueswir1 已提交
4434
            }
B
blueswir1 已提交
4435 4436 4437
            if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
                (xop > 0x17 && xop <= 0x1d ) ||
                (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
B
blueswir1 已提交
4438
                switch (xop) {
4439
                case 0x0:       /* ld, V9 lduw, load unsigned word */
B
blueswir1 已提交
4440
                    gen_address_mask(dc, cpu_addr);
4441
                    tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4442
                    break;
4443
                case 0x1:       /* ldub, load unsigned byte */
B
blueswir1 已提交
4444
                    gen_address_mask(dc, cpu_addr);
4445
                    tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4446
                    break;
4447
                case 0x2:       /* lduh, load unsigned halfword */
B
blueswir1 已提交
4448
                    gen_address_mask(dc, cpu_addr);
4449
                    tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4450
                    break;
4451
                case 0x3:       /* ldd, load double word */
B
blueswir1 已提交
4452
                    if (rd & 1)
4453
                        goto illegal_insn;
B
blueswir1 已提交
4454
                    else {
P
pbrook 已提交
4455
                        TCGv_i32 r_const;
B
blueswir1 已提交
4456

4457
                        save_state(dc, cpu_cond);
B
blueswir1 已提交
4458
                        r_const = tcg_const_i32(7);
P
pbrook 已提交
4459 4460
                        gen_helper_check_align(cpu_addr, r_const); // XXX remove
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4461
                        gen_address_mask(dc, cpu_addr);
4462
                        tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
4463 4464 4465
                        tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
                        tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL);
                        gen_movl_TN_reg(rd + 1, cpu_tmp0);
B
blueswir1 已提交
4466
                        tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
4467 4468
                        tcg_gen_trunc_i64_tl(cpu_val, cpu_tmp64);
                        tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL);
B
blueswir1 已提交
4469
                    }
B
blueswir1 已提交
4470
                    break;
4471
                case 0x9:       /* ldsb, load signed byte */
B
blueswir1 已提交
4472
                    gen_address_mask(dc, cpu_addr);
4473
                    tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4474
                    break;
4475
                case 0xa:       /* ldsh, load signed halfword */
B
blueswir1 已提交
4476
                    gen_address_mask(dc, cpu_addr);
4477
                    tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4478 4479
                    break;
                case 0xd:       /* ldstub -- XXX: should be atomically */
B
blueswir1 已提交
4480 4481 4482
                    {
                        TCGv r_const;

B
blueswir1 已提交
4483
                        gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4484 4485 4486 4487 4488
                        tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
                        r_const = tcg_const_tl(0xff);
                        tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
                        tcg_temp_free(r_const);
                    }
B
blueswir1 已提交
4489
                    break;
4490
                case 0x0f:      /* swap, swap register with memory. Also
B
blueswir1 已提交
4491
                                   atomically */
B
blueswir1 已提交
4492
                    CHECK_IU_FEATURE(dc, SWAP);
4493
                    gen_movl_reg_TN(rd, cpu_val);
B
blueswir1 已提交
4494
                    gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4495
                    tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
4496
                    tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4497
                    tcg_gen_mov_tl(cpu_val, cpu_tmp0);
B
blueswir1 已提交
4498
                    break;
B
bellard 已提交
4499
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
4500
                case 0x10:      /* lda, V9 lduwa, load word alternate */
B
bellard 已提交
4501
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4502 4503 4504 4505
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4506
#endif
4507
                    save_state(dc, cpu_cond);
4508
                    gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
B
blueswir1 已提交
4509
                    break;
4510
                case 0x11:      /* lduba, load unsigned byte alternate */
B
bellard 已提交
4511
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4512 4513 4514 4515 4516
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
4517
                    save_state(dc, cpu_cond);
4518
                    gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
B
blueswir1 已提交
4519
                    break;
4520
                case 0x12:      /* lduha, load unsigned halfword alternate */
B
bellard 已提交
4521
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4522 4523 4524 4525
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4526
#endif
4527
                    save_state(dc, cpu_cond);
4528
                    gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
B
blueswir1 已提交
4529
                    break;
4530
                case 0x13:      /* ldda, load double word alternate */
B
bellard 已提交
4531
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4532 4533 4534 4535
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4536
#endif
B
blueswir1 已提交
4537
                    if (rd & 1)
4538
                        goto illegal_insn;
4539
                    save_state(dc, cpu_cond);
B
blueswir1 已提交
4540 4541
                    gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
                    goto skip_move;
4542
                case 0x19:      /* ldsba, load signed byte alternate */
B
bellard 已提交
4543
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4544 4545 4546 4547 4548
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
4549
                    save_state(dc, cpu_cond);
4550
                    gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
B
blueswir1 已提交
4551
                    break;
4552
                case 0x1a:      /* ldsha, load signed halfword alternate */
B
bellard 已提交
4553
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4554 4555 4556 4557
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4558
#endif
4559
                    save_state(dc, cpu_cond);
4560
                    gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
B
blueswir1 已提交
4561 4562
                    break;
                case 0x1d:      /* ldstuba -- XXX: should be atomically */
B
bellard 已提交
4563
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4564 4565 4566 4567 4568
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
4569
                    save_state(dc, cpu_cond);
4570
                    gen_ldstub_asi(cpu_val, cpu_addr, insn);
B
blueswir1 已提交
4571
                    break;
4572
                case 0x1f:      /* swapa, swap reg with alt. memory. Also
B
blueswir1 已提交
4573
                                   atomically */
B
blueswir1 已提交
4574
                    CHECK_IU_FEATURE(dc, SWAP);
B
bellard 已提交
4575
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4576 4577 4578 4579
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4580
#endif
4581
                    save_state(dc, cpu_cond);
4582 4583
                    gen_movl_reg_TN(rd, cpu_val);
                    gen_swap_asi(cpu_val, cpu_addr, insn);
B
blueswir1 已提交
4584
                    break;
B
bellard 已提交
4585 4586

#ifndef TARGET_SPARC64
B
blueswir1 已提交
4587 4588 4589 4590
                case 0x30: /* ldc */
                case 0x31: /* ldcsr */
                case 0x33: /* lddc */
                    goto ncp_insn;
B
bellard 已提交
4591 4592 4593
#endif
#endif
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4594
                case 0x08: /* V9 ldsw */
B
blueswir1 已提交
4595
                    gen_address_mask(dc, cpu_addr);
4596
                    tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4597 4598
                    break;
                case 0x0b: /* V9 ldx */
B
blueswir1 已提交
4599
                    gen_address_mask(dc, cpu_addr);
4600
                    tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4601 4602
                    break;
                case 0x18: /* V9 ldswa */
4603
                    save_state(dc, cpu_cond);
4604
                    gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
B
blueswir1 已提交
4605 4606
                    break;
                case 0x1b: /* V9 ldxa */
4607
                    save_state(dc, cpu_cond);
4608
                    gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
B
blueswir1 已提交
4609 4610 4611 4612
                    break;
                case 0x2d: /* V9 prefetch, no effect */
                    goto skip_move;
                case 0x30: /* V9 ldfa */
4613 4614 4615
                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
                        goto jmp_insn;
                    }
4616
                    save_state(dc, cpu_cond);
4617
                    gen_ldf_asi(cpu_addr, insn, 4, rd);
4618
                    gen_update_fprs_dirty(rd);
4619
                    goto skip_move;
B
blueswir1 已提交
4620
                case 0x33: /* V9 lddfa */
4621 4622 4623
                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
                        goto jmp_insn;
                    }
4624
                    save_state(dc, cpu_cond);
4625
                    gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
4626
                    gen_update_fprs_dirty(DFPREG(rd));
4627
                    goto skip_move;
B
blueswir1 已提交
4628 4629 4630
                case 0x3d: /* V9 prefetcha, no effect */
                    goto skip_move;
                case 0x32: /* V9 ldqfa */
B
blueswir1 已提交
4631
                    CHECK_FPU_FEATURE(dc, FLOAT128);
4632 4633 4634
                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
                        goto jmp_insn;
                    }
4635
                    save_state(dc, cpu_cond);
4636
                    gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
4637
                    gen_update_fprs_dirty(QFPREG(rd));
B
blueswir1 已提交
4638
                    goto skip_move;
B
blueswir1 已提交
4639 4640 4641 4642
#endif
                default:
                    goto illegal_insn;
                }
4643
                gen_movl_TN_reg(rd, cpu_val);
B
blueswir1 已提交
4644
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
B
blueswir1 已提交
4645
            skip_move: ;
B
bellard 已提交
4646
#endif
B
blueswir1 已提交
4647
            } else if (xop >= 0x20 && xop < 0x24) {
4648
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
4649
                    goto jmp_insn;
4650
                save_state(dc, cpu_cond);
B
blueswir1 已提交
4651
                switch (xop) {
4652
                case 0x20:      /* ldf, load fpreg */
B
blueswir1 已提交
4653
                    gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4654
                    tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
4655 4656 4657
                    cpu_dst_32 = gen_dest_fpr_F();
                    tcg_gen_trunc_tl_i32(cpu_dst_32, cpu_tmp0);
                    gen_store_fpr_F(dc, rd, cpu_dst_32);
B
blueswir1 已提交
4658
                    break;
4659 4660
                case 0x21:      /* ldfsr, V9 ldxfsr */
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4661
                    gen_address_mask(dc, cpu_addr);
4662 4663
                    if (rd == 1) {
                        tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
4664
                        gen_helper_ldxfsr(cpu_env, cpu_tmp64);
I
Igor V. Kovalenko 已提交
4665 4666 4667
                    } else {
                        tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
                        tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
4668
                        gen_helper_ldfsr(cpu_env, cpu_tmp32);
I
Igor V. Kovalenko 已提交
4669
                    }
4670 4671 4672
#else
                    {
                        tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
4673
                        gen_helper_ldfsr(cpu_env, cpu_tmp32);
4674 4675
                    }
#endif
B
blueswir1 已提交
4676
                    break;
4677
                case 0x22:      /* ldqf, load quad fpreg */
B
blueswir1 已提交
4678
                    {
P
pbrook 已提交
4679
                        TCGv_i32 r_const;
B
blueswir1 已提交
4680 4681 4682

                        CHECK_FPU_FEATURE(dc, FLOAT128);
                        r_const = tcg_const_i32(dc->mem_idx);
4683
                        gen_address_mask(dc, cpu_addr);
P
pbrook 已提交
4684 4685
                        gen_helper_ldqf(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4686
                        gen_op_store_QT0_fpr(QFPREG(rd));
4687
                        gen_update_fprs_dirty(QFPREG(rd));
B
blueswir1 已提交
4688
                    }
B
blueswir1 已提交
4689
                    break;
4690
                case 0x23:      /* lddf, load double fpreg */
4691 4692 4693 4694
                    gen_address_mask(dc, cpu_addr);
                    cpu_dst_64 = gen_dest_fpr_D();
                    tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx);
                    gen_store_fpr_D(dc, rd, cpu_dst_64);
B
blueswir1 已提交
4695 4696 4697 4698
                    break;
                default:
                    goto illegal_insn;
                }
B
Blue Swirl 已提交
4699
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
B
blueswir1 已提交
4700
                       xop == 0xe || xop == 0x1e) {
4701
                gen_movl_reg_TN(rd, cpu_val);
B
blueswir1 已提交
4702
                switch (xop) {
4703
                case 0x4: /* st, store word */
B
blueswir1 已提交
4704
                    gen_address_mask(dc, cpu_addr);
4705
                    tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4706
                    break;
4707
                case 0x5: /* stb, store byte */
B
blueswir1 已提交
4708
                    gen_address_mask(dc, cpu_addr);
4709
                    tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4710
                    break;
4711
                case 0x6: /* sth, store halfword */
B
blueswir1 已提交
4712
                    gen_address_mask(dc, cpu_addr);
4713
                    tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4714
                    break;
4715
                case 0x7: /* std, store double word */
B
blueswir1 已提交
4716
                    if (rd & 1)
4717
                        goto illegal_insn;
B
blueswir1 已提交
4718
                    else {
P
pbrook 已提交
4719
                        TCGv_i32 r_const;
B
blueswir1 已提交
4720

4721
                        save_state(dc, cpu_cond);
B
blueswir1 已提交
4722
                        gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4723
                        r_const = tcg_const_i32(7);
P
pbrook 已提交
4724 4725
                        gen_helper_check_align(cpu_addr, r_const); // XXX remove
                        tcg_temp_free_i32(r_const);
4726
                        gen_movl_reg_TN(rd + 1, cpu_tmp0);
4727
                        tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
4728
                        tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4729
                    }
B
blueswir1 已提交
4730
                    break;
B
bellard 已提交
4731
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
4732
                case 0x14: /* sta, V9 stwa, store word alternate */
B
bellard 已提交
4733
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4734 4735 4736 4737
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4738
#endif
4739
                    save_state(dc, cpu_cond);
4740
                    gen_st_asi(cpu_val, cpu_addr, insn, 4);
4741
                    dc->npc = DYNAMIC_PC;
B
bellard 已提交
4742
                    break;
4743
                case 0x15: /* stba, store byte alternate */
B
bellard 已提交
4744
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4745 4746 4747 4748
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4749
#endif
4750
                    save_state(dc, cpu_cond);
4751
                    gen_st_asi(cpu_val, cpu_addr, insn, 1);
4752
                    dc->npc = DYNAMIC_PC;
B
bellard 已提交
4753
                    break;
4754
                case 0x16: /* stha, store halfword alternate */
B
bellard 已提交
4755
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4756 4757 4758 4759
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4760
#endif
4761
                    save_state(dc, cpu_cond);
4762
                    gen_st_asi(cpu_val, cpu_addr, insn, 2);
4763
                    dc->npc = DYNAMIC_PC;
B
bellard 已提交
4764
                    break;
4765
                case 0x17: /* stda, store double word alternate */
B
bellard 已提交
4766
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4767 4768 4769 4770
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4771
#endif
B
blueswir1 已提交
4772
                    if (rd & 1)
4773
                        goto illegal_insn;
B
blueswir1 已提交
4774
                    else {
4775
                        save_state(dc, cpu_cond);
4776
                        gen_stda_asi(cpu_val, cpu_addr, insn, rd);
B
blueswir1 已提交
4777
                    }
B
bellard 已提交
4778
                    break;
B
bellard 已提交
4779
#endif
B
bellard 已提交
4780
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4781
                case 0x0e: /* V9 stx */
B
blueswir1 已提交
4782
                    gen_address_mask(dc, cpu_addr);
4783
                    tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4784 4785
                    break;
                case 0x1e: /* V9 stxa */
4786
                    save_state(dc, cpu_cond);
4787
                    gen_st_asi(cpu_val, cpu_addr, insn, 8);
4788
                    dc->npc = DYNAMIC_PC;
B
blueswir1 已提交
4789
                    break;
B
bellard 已提交
4790
#endif
B
blueswir1 已提交
4791 4792 4793 4794
                default:
                    goto illegal_insn;
                }
            } else if (xop > 0x23 && xop < 0x28) {
4795
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
4796
                    goto jmp_insn;
4797
                save_state(dc, cpu_cond);
B
blueswir1 已提交
4798
                switch (xop) {
4799
                case 0x24: /* stf, store fpreg */
B
blueswir1 已提交
4800
                    gen_address_mask(dc, cpu_addr);
4801 4802
                    cpu_src1_32 = gen_load_fpr_F(dc, rd);
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_src1_32);
B
blueswir1 已提交
4803
                    tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4804 4805
                    break;
                case 0x25: /* stfsr, V9 stxfsr */
4806
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4807
                    gen_address_mask(dc, cpu_addr);
4808 4809 4810
                    tcg_gen_ld_i64(cpu_tmp64, cpu_env, offsetof(CPUState, fsr));
                    if (rd == 1)
                        tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4811 4812
                    else
                        tcg_gen_qemu_st32(cpu_tmp64, cpu_addr, dc->mem_idx);
4813 4814
#else
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUState, fsr));
4815
                    tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
4816
#endif
B
blueswir1 已提交
4817
                    break;
B
blueswir1 已提交
4818 4819 4820
                case 0x26:
#ifdef TARGET_SPARC64
                    /* V9 stqf, store quad fpreg */
B
blueswir1 已提交
4821
                    {
P
pbrook 已提交
4822
                        TCGv_i32 r_const;
B
blueswir1 已提交
4823 4824 4825 4826

                        CHECK_FPU_FEATURE(dc, FLOAT128);
                        gen_op_load_fpr_QT0(QFPREG(rd));
                        r_const = tcg_const_i32(dc->mem_idx);
4827
                        gen_address_mask(dc, cpu_addr);
P
pbrook 已提交
4828 4829
                        gen_helper_stqf(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4830
                    }
B
blueswir1 已提交
4831 4832 4833 4834 4835 4836
                    break;
#else /* !TARGET_SPARC64 */
                    /* stdfq, store floating point queue */
#if defined(CONFIG_USER_ONLY)
                    goto illegal_insn;
#else
B
blueswir1 已提交
4837 4838
                    if (!supervisor(dc))
                        goto priv_insn;
4839
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
blueswir1 已提交
4840 4841
                        goto jmp_insn;
                    goto nfq_insn;
B
blueswir1 已提交
4842
#endif
B
blueswir1 已提交
4843
#endif
4844
                case 0x27: /* stdf, store double fpreg */
4845 4846 4847
                    gen_address_mask(dc, cpu_addr);
                    cpu_src1_64 = gen_load_fpr_D(dc, rd);
                    tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4848 4849 4850 4851 4852
                    break;
                default:
                    goto illegal_insn;
                }
            } else if (xop > 0x33 && xop < 0x3f) {
4853
                save_state(dc, cpu_cond);
B
blueswir1 已提交
4854
                switch (xop) {
4855
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4856
                case 0x34: /* V9 stfa */
4857 4858 4859
                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
                        goto jmp_insn;
                    }
4860
                    gen_stf_asi(cpu_addr, insn, 4, rd);
B
blueswir1 已提交
4861
                    break;
B
blueswir1 已提交
4862
                case 0x36: /* V9 stqfa */
B
blueswir1 已提交
4863
                    {
P
pbrook 已提交
4864
                        TCGv_i32 r_const;
B
blueswir1 已提交
4865 4866

                        CHECK_FPU_FEATURE(dc, FLOAT128);
4867 4868 4869
                        if (gen_trap_ifnofpu(dc, cpu_cond)) {
                            goto jmp_insn;
                        }
B
blueswir1 已提交
4870
                        r_const = tcg_const_i32(7);
P
pbrook 已提交
4871 4872
                        gen_helper_check_align(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4873 4874
                        gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
                    }
B
blueswir1 已提交
4875
                    break;
B
blueswir1 已提交
4876
                case 0x37: /* V9 stdfa */
4877 4878 4879
                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
                        goto jmp_insn;
                    }
4880
                    gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
B
blueswir1 已提交
4881 4882
                    break;
                case 0x3c: /* V9 casa */
B
blueswir1 已提交
4883
                    gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
4884
                    gen_movl_TN_reg(rd, cpu_val);
B
blueswir1 已提交
4885 4886
                    break;
                case 0x3e: /* V9 casxa */
B
blueswir1 已提交
4887
                    gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
4888
                    gen_movl_TN_reg(rd, cpu_val);
B
blueswir1 已提交
4889
                    break;
4890
#else
B
blueswir1 已提交
4891 4892 4893 4894 4895 4896 4897 4898 4899
                case 0x34: /* stc */
                case 0x35: /* stcsr */
                case 0x36: /* stdcq */
                case 0x37: /* stdc */
                    goto ncp_insn;
#endif
                default:
                    goto illegal_insn;
                }
B
Blue Swirl 已提交
4900
            } else
B
blueswir1 已提交
4901 4902 4903
                goto illegal_insn;
        }
        break;
4904 4905
    }
    /* default case for non jump instructions */
B
bellard 已提交
4906
    if (dc->npc == DYNAMIC_PC) {
B
blueswir1 已提交
4907 4908
        dc->pc = DYNAMIC_PC;
        gen_op_next_insn();
B
bellard 已提交
4909 4910
    } else if (dc->npc == JUMP_PC) {
        /* we can do a static jump */
4911
        gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
B
bellard 已提交
4912 4913
        dc->is_br = 1;
    } else {
B
blueswir1 已提交
4914 4915
        dc->pc = dc->npc;
        dc->npc = dc->npc + 4;
4916
    }
B
bellard 已提交
4917
 jmp_insn:
4918
    goto egress;
4919
 illegal_insn:
B
blueswir1 已提交
4920
    {
P
pbrook 已提交
4921
        TCGv_i32 r_const;
B
blueswir1 已提交
4922 4923 4924

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_ILL_INSN);
4925
        gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
4926
        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4927 4928
        dc->is_br = 1;
    }
4929
    goto egress;
B
blueswir1 已提交
4930
 unimp_flush:
B
blueswir1 已提交
4931
    {
P
pbrook 已提交
4932
        TCGv_i32 r_const;
B
blueswir1 已提交
4933 4934 4935

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_UNIMP_FLUSH);
4936
        gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
4937
        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4938 4939
        dc->is_br = 1;
    }
4940
    goto egress;
B
bellard 已提交
4941
#if !defined(CONFIG_USER_ONLY)
4942
 priv_insn:
B
blueswir1 已提交
4943
    {
P
pbrook 已提交
4944
        TCGv_i32 r_const;
B
blueswir1 已提交
4945 4946 4947

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_PRIV_INSN);
4948
        gen_helper_raise_exception(cpu_env, r_const);
P
pbrook 已提交
4949
        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4950 4951
        dc->is_br = 1;
    }
4952
    goto egress;
B
blueswir1 已提交
4953
#endif
B
bellard 已提交
4954
 nfpu_insn:
4955
    save_state(dc, cpu_cond);
B
bellard 已提交
4956 4957
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
    dc->is_br = 1;
4958
    goto egress;
B
blueswir1 已提交
4959
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
B
blueswir1 已提交
4960
 nfq_insn:
4961
    save_state(dc, cpu_cond);
B
blueswir1 已提交
4962 4963
    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
    dc->is_br = 1;
4964
    goto egress;
B
blueswir1 已提交
4965
#endif
4966 4967
#ifndef TARGET_SPARC64
 ncp_insn:
B
blueswir1 已提交
4968 4969 4970 4971 4972
    {
        TCGv r_const;

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_NCP_INSN);
4973
        gen_helper_raise_exception(cpu_env, r_const);
B
blueswir1 已提交
4974 4975 4976
        tcg_temp_free(r_const);
        dc->is_br = 1;
    }
4977
    goto egress;
4978
#endif
4979 4980 4981
 egress:
    tcg_temp_free(cpu_tmp1);
    tcg_temp_free(cpu_tmp2);
4982 4983 4984 4985 4986 4987 4988
    if (dc->n_t32 != 0) {
        int i;
        for (i = dc->n_t32 - 1; i >= 0; --i) {
            tcg_temp_free_i32(dc->t32[i]);
        }
        dc->n_t32 = 0;
    }
4989 4990
}

4991 4992
static inline void gen_intermediate_code_internal(TranslationBlock * tb,
                                                  int spc, CPUSPARCState *env)
4993
{
B
bellard 已提交
4994
    target_ulong pc_start, last_pc;
4995 4996
    uint16_t *gen_opc_end;
    DisasContext dc1, *dc = &dc1;
4997
    CPUBreakpoint *bp;
4998
    int j, lj = -1;
P
pbrook 已提交
4999 5000
    int num_insns;
    int max_insns;
5001 5002 5003

    memset(dc, 0, sizeof(DisasContext));
    dc->tb = tb;
B
bellard 已提交
5004
    pc_start = tb->pc;
5005
    dc->pc = pc_start;
B
bellard 已提交
5006
    last_pc = dc->pc;
B
bellard 已提交
5007
    dc->npc = (target_ulong) tb->cs_base;
5008
    dc->cc_op = CC_OP_DYNAMIC;
B
blueswir1 已提交
5009
    dc->mem_idx = cpu_mmu_index(env);
5010
    dc->def = env->def;
5011 5012
    dc->fpu_enabled = tb_fpu_enabled(tb->flags);
    dc->address_mask_32bit = tb_am_enabled(tb->flags);
5013
    dc->singlestep = (env->singlestep_enabled || singlestep);
5014 5015
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

P
pbrook 已提交
5016 5017 5018
    cpu_tmp0 = tcg_temp_new();
    cpu_tmp32 = tcg_temp_new_i32();
    cpu_tmp64 = tcg_temp_new_i64();
B
blueswir1 已提交
5019

P
pbrook 已提交
5020
    cpu_dst = tcg_temp_local_new();
B
blueswir1 已提交
5021 5022

    // loads and stores
P
pbrook 已提交
5023 5024
    cpu_val = tcg_temp_local_new();
    cpu_addr = tcg_temp_local_new();
B
blueswir1 已提交
5025

P
pbrook 已提交
5026 5027 5028 5029 5030
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;
    gen_icount_start();
5031
    do {
B
Blue Swirl 已提交
5032 5033
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
5034
                if (bp->pc == dc->pc) {
B
blueswir1 已提交
5035
                    if (dc->pc != pc_start)
5036
                        save_state(dc, cpu_cond);
5037
                    gen_helper_debug(cpu_env);
B
bellard 已提交
5038
                    tcg_gen_exit_tb(0);
B
blueswir1 已提交
5039
                    dc->is_br = 1;
B
bellard 已提交
5040
                    goto exit_gen_loop;
5041 5042 5043 5044
                }
            }
        }
        if (spc) {
5045
            qemu_log("Search PC...\n");
5046 5047 5048 5049 5050 5051 5052 5053
            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;
P
pbrook 已提交
5054
                gen_opc_icount[lj] = num_insns;
5055 5056
            }
        }
P
pbrook 已提交
5057 5058
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
B
blueswir1 已提交
5059 5060
        last_pc = dc->pc;
        disas_sparc_insn(dc);
P
pbrook 已提交
5061
        num_insns++;
B
blueswir1 已提交
5062 5063 5064 5065 5066 5067

        if (dc->is_br)
            break;
        /* if the next PC is different, we abort now */
        if (dc->pc != (last_pc + 4))
            break;
B
bellard 已提交
5068 5069 5070 5071
        /* 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 已提交
5072 5073
        /* if single step mode, we generate only one instruction and
           generate an exception */
5074
        if (dc->singlestep) {
B
bellard 已提交
5075 5076
            break;
        }
5077
    } while ((gen_opc_ptr < gen_opc_end) &&
P
pbrook 已提交
5078 5079
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
             num_insns < max_insns);
B
bellard 已提交
5080 5081

 exit_gen_loop:
B
blueswir1 已提交
5082
    tcg_temp_free(cpu_addr);
B
blueswir1 已提交
5083
    tcg_temp_free(cpu_val);
B
blueswir1 已提交
5084
    tcg_temp_free(cpu_dst);
P
pbrook 已提交
5085 5086
    tcg_temp_free_i64(cpu_tmp64);
    tcg_temp_free_i32(cpu_tmp32);
B
blueswir1 已提交
5087
    tcg_temp_free(cpu_tmp0);
5088

P
pbrook 已提交
5089 5090
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
B
bellard 已提交
5091
    if (!dc->is_br) {
5092
        if (dc->pc != DYNAMIC_PC &&
B
bellard 已提交
5093 5094
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
            /* static PC and NPC: we can use direct chaining */
B
blueswir1 已提交
5095
            gen_goto_tb(dc, 0, dc->pc, dc->npc);
B
bellard 已提交
5096 5097
        } else {
            if (dc->pc != DYNAMIC_PC)
B
blueswir1 已提交
5098
                tcg_gen_movi_tl(cpu_pc, dc->pc);
5099
            save_npc(dc, cpu_cond);
B
bellard 已提交
5100
            tcg_gen_exit_tb(0);
B
bellard 已提交
5101 5102
        }
    }
P
pbrook 已提交
5103
    gen_icount_end(tb, num_insns);
5104
    *gen_opc_ptr = INDEX_op_end;
5105 5106 5107 5108 5109 5110
    if (spc) {
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
#if 0
5111
        log_page_dump();
5112
#endif
5113 5114
        gen_opc_jump_pc[0] = dc->jump_pc[0];
        gen_opc_jump_pc[1] = dc->jump_pc[1];
5115
    } else {
B
bellard 已提交
5116
        tb->size = last_pc + 4 - pc_start;
P
pbrook 已提交
5117
        tb->icount = num_insns;
5118
    }
5119
#ifdef DEBUG_DISAS
5120
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
5121 5122 5123 5124
        qemu_log("--------------\n");
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(pc_start, last_pc + 4 - pc_start, 0);
        qemu_log("\n");
5125
    }
5126 5127 5128
#endif
}

5129
void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
5130
{
5131
    gen_intermediate_code_internal(tb, 0, env);
5132 5133
}

5134
void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
5135
{
5136
    gen_intermediate_code_internal(tb, 1, env);
5137 5138
}

5139
void gen_intermediate_code_init(CPUSPARCState *env)
B
bellard 已提交
5140
{
B
blueswir1 已提交
5141
    unsigned int i;
5142
    static int inited;
B
blueswir1 已提交
5143 5144 5145 5146 5147 5148 5149 5150 5151 5152
    static const char * const gregnames[8] = {
        NULL, // g0 not used
        "g1",
        "g2",
        "g3",
        "g4",
        "g5",
        "g6",
        "g7",
    };
5153 5154 5155 5156 5157
    static const char * const fregnames[32] = {
        "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
        "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
        "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
        "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
B
blueswir1 已提交
5158
    };
B
bellard 已提交
5159

B
blueswir1 已提交
5160 5161 5162 5163
    /* init various static tables */
    if (!inited) {
        inited = 1;

P
pbrook 已提交
5164 5165 5166 5167
        cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
        cpu_regwptr = tcg_global_mem_new_ptr(TCG_AREG0,
                                             offsetof(CPUState, regwptr),
                                             "regwptr");
B
blueswir1 已提交
5168
#ifdef TARGET_SPARC64
P
pbrook 已提交
5169 5170 5171 5172 5173 5174 5175
        cpu_xcc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, xcc),
                                         "xcc");
        cpu_asi = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, asi),
                                         "asi");
        cpu_fprs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, fprs),
                                          "fprs");
        cpu_gsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, gsr),
5176
                                     "gsr");
P
pbrook 已提交
5177
        cpu_tick_cmpr = tcg_global_mem_new(TCG_AREG0,
5178 5179
                                           offsetof(CPUState, tick_cmpr),
                                           "tick_cmpr");
P
pbrook 已提交
5180
        cpu_stick_cmpr = tcg_global_mem_new(TCG_AREG0,
5181 5182
                                            offsetof(CPUState, stick_cmpr),
                                            "stick_cmpr");
P
pbrook 已提交
5183
        cpu_hstick_cmpr = tcg_global_mem_new(TCG_AREG0,
5184 5185
                                             offsetof(CPUState, hstick_cmpr),
                                             "hstick_cmpr");
P
pbrook 已提交
5186
        cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, hintp),
5187
                                       "hintp");
P
pbrook 已提交
5188 5189 5190 5191 5192
        cpu_htba = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, htba),
                                      "htba");
        cpu_hver = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, hver),
                                      "hver");
        cpu_ssr = tcg_global_mem_new(TCG_AREG0,
5193
                                     offsetof(CPUState, ssr), "ssr");
P
pbrook 已提交
5194
        cpu_ver = tcg_global_mem_new(TCG_AREG0,
5195
                                     offsetof(CPUState, version), "ver");
P
pbrook 已提交
5196 5197 5198
        cpu_softint = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, softint),
                                             "softint");
5199
#else
P
pbrook 已提交
5200
        cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, wim),
5201
                                     "wim");
B
blueswir1 已提交
5202
#endif
P
pbrook 已提交
5203
        cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cond),
B
blueswir1 已提交
5204
                                      "cond");
P
pbrook 已提交
5205
        cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src),
5206
                                        "cc_src");
P
pbrook 已提交
5207
        cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0,
B
blueswir1 已提交
5208 5209
                                         offsetof(CPUState, cc_src2),
                                         "cc_src2");
P
pbrook 已提交
5210
        cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst),
5211
                                        "cc_dst");
5212 5213
        cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, cc_op),
                                           "cc_op");
P
pbrook 已提交
5214 5215 5216
        cpu_psr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, psr),
                                         "psr");
        cpu_fsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, fsr),
B
blueswir1 已提交
5217
                                     "fsr");
P
pbrook 已提交
5218
        cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, pc),
B
blueswir1 已提交
5219
                                    "pc");
P
pbrook 已提交
5220 5221 5222
        cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, npc),
                                     "npc");
        cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, y), "y");
5223
#ifndef CONFIG_USER_ONLY
P
pbrook 已提交
5224
        cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, tbr),
5225 5226
                                     "tbr");
#endif
5227
        for (i = 1; i < 8; i++) {
P
pbrook 已提交
5228
            cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
B
blueswir1 已提交
5229 5230
                                              offsetof(CPUState, gregs[i]),
                                              gregnames[i]);
5231 5232 5233
        }
        for (i = 0; i < TARGET_DPREGS; i++) {
            cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
5234 5235
                                                offsetof(CPUState, fpr[i]),
                                                fregnames[i]);
5236
        }
B
blueswir1 已提交
5237

B
blueswir1 已提交
5238 5239
        /* register helpers */

P
pbrook 已提交
5240
#define GEN_HELPER 2
B
blueswir1 已提交
5241
#include "helper.h"
B
blueswir1 已提交
5242
    }
B
bellard 已提交
5243
}
A
aurel32 已提交
5244

5245
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
5246 5247 5248 5249 5250 5251 5252
{
    target_ulong npc;
    env->pc = gen_opc_pc[pc_pos];
    npc = gen_opc_npc[pc_pos];
    if (npc == 1) {
        /* dynamic NPC: already stored */
    } else if (npc == 2) {
B
Blue Swirl 已提交
5253 5254
        /* jump PC: use 'cond' and the jump targets of the translation */
        if (env->cond) {
A
aurel32 已提交
5255
            env->npc = gen_opc_jump_pc[0];
B
Blue Swirl 已提交
5256
        } else {
A
aurel32 已提交
5257
            env->npc = gen_opc_jump_pc[1];
B
Blue Swirl 已提交
5258
        }
A
aurel32 已提交
5259 5260 5261
    } else {
        env->npc = npc;
    }
5262 5263 5264

    /* flush pending conditional evaluations before exposing cpu state */
    if (CC_OP != CC_OP_FLAGS) {
5265
        helper_compute_psr(env);
5266
    }
A
aurel32 已提交
5267
}