translate.c 189.5 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 29
 */

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

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

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

36 37
#define DEBUG_DISAS

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

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

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

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

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

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

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

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

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

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

B
blueswir1 已提交
118 119 120
/* floating point registers moves */
static void gen_op_load_fpr_DT0(unsigned int src)
{
B
blueswir1 已提交
121
    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, dt0) +
B
blueswir1 已提交
122
                   offsetof(CPU_DoubleU, l.upper));
B
blueswir1 已提交
123
    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, dt0) +
B
blueswir1 已提交
124
                   offsetof(CPU_DoubleU, l.lower));
B
blueswir1 已提交
125 126 127 128
}

static void gen_op_load_fpr_DT1(unsigned int src)
{
B
blueswir1 已提交
129
    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, dt1) +
B
blueswir1 已提交
130
                   offsetof(CPU_DoubleU, l.upper));
B
blueswir1 已提交
131
    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, dt1) +
B
blueswir1 已提交
132
                   offsetof(CPU_DoubleU, l.lower));
B
blueswir1 已提交
133 134 135 136
}

static void gen_op_store_DT0_fpr(unsigned int dst)
{
B
blueswir1 已提交
137
    tcg_gen_ld_i32(cpu_fpr[dst], cpu_env, offsetof(CPUSPARCState, dt0) +
B
blueswir1 已提交
138
                   offsetof(CPU_DoubleU, l.upper));
B
blueswir1 已提交
139
    tcg_gen_ld_i32(cpu_fpr[dst + 1], cpu_env, offsetof(CPUSPARCState, dt0) +
B
blueswir1 已提交
140
                   offsetof(CPU_DoubleU, l.lower));
B
blueswir1 已提交
141 142 143 144
}

static void gen_op_load_fpr_QT0(unsigned int src)
{
B
blueswir1 已提交
145
    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
146
                   offsetof(CPU_QuadU, l.upmost));
B
blueswir1 已提交
147
    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
148
                   offsetof(CPU_QuadU, l.upper));
B
blueswir1 已提交
149
    tcg_gen_st_i32(cpu_fpr[src + 2], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
150
                   offsetof(CPU_QuadU, l.lower));
B
blueswir1 已提交
151
    tcg_gen_st_i32(cpu_fpr[src + 3], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
152
                   offsetof(CPU_QuadU, l.lowest));
B
blueswir1 已提交
153 154 155 156
}

static void gen_op_load_fpr_QT1(unsigned int src)
{
B
blueswir1 已提交
157
    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, qt1) +
B
blueswir1 已提交
158
                   offsetof(CPU_QuadU, l.upmost));
B
blueswir1 已提交
159
    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
B
blueswir1 已提交
160
                   offsetof(CPU_QuadU, l.upper));
B
blueswir1 已提交
161
    tcg_gen_st_i32(cpu_fpr[src + 2], cpu_env, offsetof(CPUSPARCState, qt1) +
B
blueswir1 已提交
162
                   offsetof(CPU_QuadU, l.lower));
B
blueswir1 已提交
163
    tcg_gen_st_i32(cpu_fpr[src + 3], cpu_env, offsetof(CPUSPARCState, qt1) +
B
blueswir1 已提交
164
                   offsetof(CPU_QuadU, l.lowest));
B
blueswir1 已提交
165 166 167 168
}

static void gen_op_store_QT0_fpr(unsigned int dst)
{
B
blueswir1 已提交
169
    tcg_gen_ld_i32(cpu_fpr[dst], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
170
                   offsetof(CPU_QuadU, l.upmost));
B
blueswir1 已提交
171
    tcg_gen_ld_i32(cpu_fpr[dst + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
172
                   offsetof(CPU_QuadU, l.upper));
B
blueswir1 已提交
173
    tcg_gen_ld_i32(cpu_fpr[dst + 2], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
174
                   offsetof(CPU_QuadU, l.lower));
B
blueswir1 已提交
175
    tcg_gen_ld_i32(cpu_fpr[dst + 3], cpu_env, offsetof(CPUSPARCState, qt0) +
B
blueswir1 已提交
176
                   offsetof(CPU_QuadU, l.lowest));
B
blueswir1 已提交
177
}
B
blueswir1 已提交
178

179 180
/* moves */
#ifdef CONFIG_USER_ONLY
B
bellard 已提交
181
#define supervisor(dc) 0
182
#ifdef TARGET_SPARC64
B
blueswir1 已提交
183
#define hypervisor(dc) 0
184
#endif
B
bellard 已提交
185
#else
186
#define supervisor(dc) (dc->mem_idx >= MMU_KERNEL_IDX)
187
#ifdef TARGET_SPARC64
188
#define hypervisor(dc) (dc->mem_idx == MMU_HYPV_IDX)
B
blueswir1 已提交
189
#else
B
bellard 已提交
190
#endif
191 192
#endif

B
blueswir1 已提交
193 194 195
#ifdef TARGET_SPARC64
#ifndef TARGET_ABI32
#define AM_CHECK(dc) ((dc)->address_mask_32bit)
B
blueswir1 已提交
196
#else
B
blueswir1 已提交
197 198
#define AM_CHECK(dc) (1)
#endif
B
blueswir1 已提交
199
#endif
200

B
blueswir1 已提交
201 202 203 204 205 206 207 208
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 已提交
209
static inline void gen_movl_reg_TN(int reg, TCGv tn)
210
{
B
blueswir1 已提交
211 212 213
    if (reg == 0)
        tcg_gen_movi_tl(tn, 0);
    else if (reg < 8)
B
blueswir1 已提交
214
        tcg_gen_mov_tl(tn, cpu_gregs[reg]);
B
blueswir1 已提交
215 216
    else {
        tcg_gen_ld_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
217 218 219
    }
}

B
blueswir1 已提交
220
static inline void gen_movl_TN_reg(int reg, TCGv tn)
221
{
B
blueswir1 已提交
222 223 224
    if (reg == 0)
        return;
    else if (reg < 8)
B
blueswir1 已提交
225
        tcg_gen_mov_tl(cpu_gregs[reg], tn);
B
blueswir1 已提交
226 227
    else {
        tcg_gen_st_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
228 229 230
    }
}

231
static inline void gen_goto_tb(DisasContext *s, int tb_num,
232 233 234 235 236 237
                               target_ulong pc, target_ulong npc)
{
    TranslationBlock *tb;

    tb = s->tb;
    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
238 239
        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
        !s->singlestep)  {
240
        /* jump to same page: we can use a direct jump */
B
bellard 已提交
241
        tcg_gen_goto_tb(tb_num);
B
blueswir1 已提交
242 243
        tcg_gen_movi_tl(cpu_pc, pc);
        tcg_gen_movi_tl(cpu_npc, npc);
B
bellard 已提交
244
        tcg_gen_exit_tb((long)tb + tb_num);
245 246
    } else {
        /* jump to another page: currently not optimized */
B
blueswir1 已提交
247 248
        tcg_gen_movi_tl(cpu_pc, pc);
        tcg_gen_movi_tl(cpu_npc, npc);
B
bellard 已提交
249
        tcg_gen_exit_tb(0);
250 251 252
    }
}

253
// XXX suboptimal
P
pbrook 已提交
254
static inline void gen_mov_reg_N(TCGv reg, TCGv_i32 src)
255
{
B
blueswir1 已提交
256
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
257
    tcg_gen_shri_tl(reg, reg, PSR_NEG_SHIFT);
258 259 260
    tcg_gen_andi_tl(reg, reg, 0x1);
}

P
pbrook 已提交
261
static inline void gen_mov_reg_Z(TCGv reg, TCGv_i32 src)
262
{
B
blueswir1 已提交
263
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
264
    tcg_gen_shri_tl(reg, reg, PSR_ZERO_SHIFT);
265 266 267
    tcg_gen_andi_tl(reg, reg, 0x1);
}

P
pbrook 已提交
268
static inline void gen_mov_reg_V(TCGv reg, TCGv_i32 src)
269
{
B
blueswir1 已提交
270
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
271
    tcg_gen_shri_tl(reg, reg, PSR_OVF_SHIFT);
272 273 274
    tcg_gen_andi_tl(reg, reg, 0x1);
}

P
pbrook 已提交
275
static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src)
276
{
B
blueswir1 已提交
277
    tcg_gen_extu_i32_tl(reg, src);
B
blueswir1 已提交
278
    tcg_gen_shri_tl(reg, reg, PSR_CARRY_SHIFT);
279 280 281
    tcg_gen_andi_tl(reg, reg, 0x1);
}

282 283
static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
{
P
pbrook 已提交
284 285
    TCGv r_temp;
    TCGv_i32 r_const;
286 287 288 289
    int l1;

    l1 = gen_new_label();

P
pbrook 已提交
290
    r_temp = tcg_temp_new();
291
    tcg_gen_xor_tl(r_temp, src1, src2);
B
blueswir1 已提交
292
    tcg_gen_not_tl(r_temp, r_temp);
293 294
    tcg_gen_xor_tl(cpu_tmp0, src1, dst);
    tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
295
    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
P
pbrook 已提交
296
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
B
blueswir1 已提交
297
    r_const = tcg_const_i32(TT_TOVF);
P
pbrook 已提交
298 299
    gen_helper_raise_exception(r_const);
    tcg_temp_free_i32(r_const);
300
    gen_set_label(l1);
B
blueswir1 已提交
301
    tcg_temp_free(r_temp);
302 303 304 305 306
}

static inline void gen_tag_tv(TCGv src1, TCGv src2)
{
    int l1;
P
pbrook 已提交
307
    TCGv_i32 r_const;
308 309

    l1 = gen_new_label();
310 311
    tcg_gen_or_tl(cpu_tmp0, src1, src2);
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
P
pbrook 已提交
312
    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
B
blueswir1 已提交
313
    r_const = tcg_const_i32(TT_TOVF);
P
pbrook 已提交
314 315
    gen_helper_raise_exception(r_const);
    tcg_temp_free_i32(r_const);
316 317 318
    gen_set_label(l1);
}

319 320 321 322 323
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 已提交
324
    tcg_gen_mov_tl(dst, cpu_cc_dst);
325 326
}

327
static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
328
{
329
    tcg_gen_mov_tl(cpu_cc_src, src1);
330
    tcg_gen_mov_tl(cpu_cc_src2, src2);
331
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
B
Blue Swirl 已提交
332
    tcg_gen_mov_tl(dst, cpu_cc_dst);
333 334
}

335
static TCGv_i32 gen_add32_carry32(void)
336
{
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
    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;
359 360
}

361
static TCGv_i32 gen_sub32_carry32(void)
362
{
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 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
    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();
        gen_helper_compute_C_icc(carry_32);
        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;
    }
461 462
}

463
static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
464
{
465
    tcg_gen_mov_tl(cpu_cc_src, src1);
466
    tcg_gen_mov_tl(cpu_cc_src2, src2);
467 468
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    tcg_gen_mov_tl(dst, cpu_cc_dst);
469 470
}

471
static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
472
{
473
    tcg_gen_mov_tl(cpu_cc_src, src1);
474 475
    tcg_gen_mov_tl(cpu_cc_src2, src2);
    gen_tag_tv(cpu_cc_src, cpu_cc_src2);
476 477 478
    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);
479 480 481 482
}

static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
{
P
pbrook 已提交
483 484
    TCGv r_temp;
    TCGv_i32 r_const;
485 486 487 488
    int l1;

    l1 = gen_new_label();

P
pbrook 已提交
489
    r_temp = tcg_temp_new();
490
    tcg_gen_xor_tl(r_temp, src1, src2);
491 492
    tcg_gen_xor_tl(cpu_tmp0, src1, dst);
    tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
493
    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
P
pbrook 已提交
494
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
B
blueswir1 已提交
495
    r_const = tcg_const_i32(TT_TOVF);
P
pbrook 已提交
496 497
    gen_helper_raise_exception(r_const);
    tcg_temp_free_i32(r_const);
498
    gen_set_label(l1);
B
blueswir1 已提交
499
    tcg_temp_free(r_temp);
500 501
}

B
Blue Swirl 已提交
502
static inline void gen_op_subi_cc(TCGv dst, TCGv src1, target_long src2, DisasContext *dc)
503 504 505
{
    tcg_gen_mov_tl(cpu_cc_src, src1);
    tcg_gen_movi_tl(cpu_cc_src2, src2);
B
Blue Swirl 已提交
506
    if (src2 == 0) {
B
Blue Swirl 已提交
507 508 509
        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 已提交
510 511
    } else {
        tcg_gen_subi_tl(cpu_cc_dst, cpu_cc_src, src2);
B
Blue Swirl 已提交
512 513
        tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
        dc->cc_op = CC_OP_SUB;
B
Blue Swirl 已提交
514
    }
B
Blue Swirl 已提交
515
    tcg_gen_mov_tl(dst, cpu_cc_dst);
516 517 518
}

static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
519
{
520
    tcg_gen_mov_tl(cpu_cc_src, src1);
521
    tcg_gen_mov_tl(cpu_cc_src2, src2);
522
    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
B
Blue Swirl 已提交
523
    tcg_gen_mov_tl(dst, cpu_cc_dst);
524 525
}

526 527
static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
                            TCGv src2, int update_cc)
528
{
529 530
    TCGv_i32 carry_32;
    TCGv carry;
531

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
    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();
        gen_helper_compute_C_icc(carry_32);
        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;
    }
600 601
}

602
static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
603
{
604
    tcg_gen_mov_tl(cpu_cc_src, src1);
605
    tcg_gen_mov_tl(cpu_cc_src2, src2);
606 607
    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
    tcg_gen_mov_tl(dst, cpu_cc_dst);
608 609
}

610
static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
611
{
612
    tcg_gen_mov_tl(cpu_cc_src, src1);
613 614
    tcg_gen_mov_tl(cpu_cc_src2, src2);
    gen_tag_tv(cpu_cc_src, cpu_cc_src2);
615 616 617
    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);
618 619
}

620
static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
621
{
B
blueswir1 已提交
622
    TCGv r_temp;
623
    int l1;
B
blueswir1 已提交
624 625

    l1 = gen_new_label();
P
pbrook 已提交
626
    r_temp = tcg_temp_new();
B
blueswir1 已提交
627 628 629 630 631

    /* old op:
    if (!(env->y & 1))
        T1 = 0;
    */
632
    tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
633
    tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
634
    tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
B
blueswir1 已提交
635
    tcg_gen_brcondi_tl(TCG_COND_NE, r_temp, 0, l1);
B
blueswir1 已提交
636
    tcg_gen_movi_tl(cpu_cc_src2, 0);
637
    gen_set_label(l1);
B
blueswir1 已提交
638 639 640

    // b2 = T0 & 1;
    // env->y = (b2 << 31) | (env->y >> 1);
B
blueswir1 已提交
641 642
    tcg_gen_andi_tl(r_temp, cpu_cc_src, 0x1);
    tcg_gen_shli_tl(r_temp, r_temp, 31);
643
    tcg_gen_shri_tl(cpu_tmp0, cpu_y, 1);
644
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x7fffffff);
645 646
    tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, r_temp);
    tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
B
blueswir1 已提交
647 648 649 650 651

    // 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 已提交
652
    tcg_temp_free(r_temp);
B
blueswir1 已提交
653 654 655 656

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

660
    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
B
blueswir1 已提交
661

662
    tcg_gen_mov_tl(dst, cpu_cc_dst);
B
blueswir1 已提交
663 664
}

665
static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
666
{
P
pbrook 已提交
667
    TCGv_i64 r_temp, r_temp2;
B
blueswir1 已提交
668

P
pbrook 已提交
669 670
    r_temp = tcg_temp_new_i64();
    r_temp2 = tcg_temp_new_i64();
B
blueswir1 已提交
671

B
blueswir1 已提交
672 673
    tcg_gen_extu_tl_i64(r_temp, src2);
    tcg_gen_extu_tl_i64(r_temp2, src1);
B
blueswir1 已提交
674 675 676
    tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);

    tcg_gen_shri_i64(r_temp, r_temp2, 32);
B
blueswir1 已提交
677
    tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
P
pbrook 已提交
678
    tcg_temp_free_i64(r_temp);
679
    tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
B
blueswir1 已提交
680
#ifdef TARGET_SPARC64
681
    tcg_gen_mov_i64(dst, r_temp2);
B
blueswir1 已提交
682
#else
683
    tcg_gen_trunc_i64_tl(dst, r_temp2);
B
blueswir1 已提交
684
#endif
P
pbrook 已提交
685
    tcg_temp_free_i64(r_temp2);
B
blueswir1 已提交
686 687
}

688
static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
689
{
P
pbrook 已提交
690
    TCGv_i64 r_temp, r_temp2;
B
blueswir1 已提交
691

P
pbrook 已提交
692 693
    r_temp = tcg_temp_new_i64();
    r_temp2 = tcg_temp_new_i64();
B
blueswir1 已提交
694

B
blueswir1 已提交
695 696
    tcg_gen_ext_tl_i64(r_temp, src2);
    tcg_gen_ext_tl_i64(r_temp2, src1);
B
blueswir1 已提交
697 698 699
    tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);

    tcg_gen_shri_i64(r_temp, r_temp2, 32);
B
blueswir1 已提交
700
    tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
P
pbrook 已提交
701
    tcg_temp_free_i64(r_temp);
702
    tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
B
blueswir1 已提交
703
#ifdef TARGET_SPARC64
704
    tcg_gen_mov_i64(dst, r_temp2);
B
blueswir1 已提交
705
#else
706
    tcg_gen_trunc_i64_tl(dst, r_temp2);
B
blueswir1 已提交
707
#endif
P
pbrook 已提交
708
    tcg_temp_free_i64(r_temp2);
B
blueswir1 已提交
709 710
}

B
blueswir1 已提交
711
#ifdef TARGET_SPARC64
B
blueswir1 已提交
712
static inline void gen_trap_ifdivzero_tl(TCGv divisor)
B
blueswir1 已提交
713
{
P
pbrook 已提交
714
    TCGv_i32 r_const;
B
blueswir1 已提交
715 716 717
    int l1;

    l1 = gen_new_label();
P
pbrook 已提交
718
    tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
B
blueswir1 已提交
719
    r_const = tcg_const_i32(TT_DIV_ZERO);
P
pbrook 已提交
720 721
    gen_helper_raise_exception(r_const);
    tcg_temp_free_i32(r_const);
B
blueswir1 已提交
722 723 724
    gen_set_label(l1);
}

725
static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
B
blueswir1 已提交
726 727 728 729 730
{
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
731 732
    tcg_gen_mov_tl(cpu_cc_src, src1);
    tcg_gen_mov_tl(cpu_cc_src2, src2);
733
    gen_trap_ifdivzero_tl(cpu_cc_src2);
P
pbrook 已提交
734 735
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc_src, INT64_MIN, l1);
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc_src2, -1, l1);
736
    tcg_gen_movi_i64(dst, INT64_MIN);
B
blueswir1 已提交
737
    tcg_gen_br(l2);
B
blueswir1 已提交
738
    gen_set_label(l1);
739
    tcg_gen_div_i64(dst, cpu_cc_src, cpu_cc_src2);
B
blueswir1 已提交
740 741 742 743
    gen_set_label(l2);
}
#endif

744 745 746 747 748 749 750
// 1
static inline void gen_op_eval_ba(TCGv dst)
{
    tcg_gen_movi_tl(dst, 1);
}

// Z
P
pbrook 已提交
751
static inline void gen_op_eval_be(TCGv dst, TCGv_i32 src)
752 753 754 755 756
{
    gen_mov_reg_Z(dst, src);
}

// Z | (N ^ V)
P
pbrook 已提交
757
static inline void gen_op_eval_ble(TCGv dst, TCGv_i32 src)
758
{
759
    gen_mov_reg_N(cpu_tmp0, src);
760
    gen_mov_reg_V(dst, src);
761 762 763
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
    gen_mov_reg_Z(cpu_tmp0, src);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
764 765 766
}

// N ^ V
P
pbrook 已提交
767
static inline void gen_op_eval_bl(TCGv dst, TCGv_i32 src)
768
{
769
    gen_mov_reg_V(cpu_tmp0, src);
770
    gen_mov_reg_N(dst, src);
771
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
772 773 774
}

// C | Z
P
pbrook 已提交
775
static inline void gen_op_eval_bleu(TCGv dst, TCGv_i32 src)
776
{
777
    gen_mov_reg_Z(cpu_tmp0, src);
778
    gen_mov_reg_C(dst, src);
779
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
780 781 782
}

// C
P
pbrook 已提交
783
static inline void gen_op_eval_bcs(TCGv dst, TCGv_i32 src)
784 785 786 787 788
{
    gen_mov_reg_C(dst, src);
}

// V
P
pbrook 已提交
789
static inline void gen_op_eval_bvs(TCGv dst, TCGv_i32 src)
790 791 792 793 794 795 796 797 798 799 800
{
    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 已提交
801
static inline void gen_op_eval_bneg(TCGv dst, TCGv_i32 src)
802 803 804 805 806
{
    gen_mov_reg_N(dst, src);
}

// !Z
P
pbrook 已提交
807
static inline void gen_op_eval_bne(TCGv dst, TCGv_i32 src)
808 809 810 811 812 813
{
    gen_mov_reg_Z(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

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

// !(N ^ V)
P
pbrook 已提交
825
static inline void gen_op_eval_bge(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 833
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !(C | Z)
P
pbrook 已提交
834
static inline void gen_op_eval_bgu(TCGv dst, TCGv_i32 src)
835
{
836
    gen_mov_reg_Z(cpu_tmp0, src);
837
    gen_mov_reg_C(dst, src);
838
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
839 840 841 842
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !C
P
pbrook 已提交
843
static inline void gen_op_eval_bcc(TCGv dst, TCGv_i32 src)
844 845 846 847 848 849
{
    gen_mov_reg_C(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !N
P
pbrook 已提交
850
static inline void gen_op_eval_bpos(TCGv dst, TCGv_i32 src)
851 852 853 854 855 856
{
    gen_mov_reg_N(dst, src);
    tcg_gen_xori_tl(dst, dst, 0x1);
}

// !V
P
pbrook 已提交
857
static inline void gen_op_eval_bvc(TCGv dst, TCGv_i32 src)
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
{
    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)
{
873
    tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset);
874 875 876 877 878 879
    tcg_gen_andi_tl(reg, reg, 0x1);
}

static inline void gen_mov_reg_FCC1(TCGv reg, TCGv src,
                                    unsigned int fcc_offset)
{
880
    tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset);
881 882 883 884 885 886 887 888
    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);
889 890
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
891 892 893 894 895 896 897
}

// 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);
898 899
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
900 901 902 903 904 905 906 907 908 909 910 911 912 913
}

// 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);
914 915 916
    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);
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
}

// 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);
932 933
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
934 935 936 937 938 939 940
}

// 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);
941 942
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
943 944 945 946 947 948 949
}

// 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);
950 951
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_or_tl(dst, dst, cpu_tmp0);
952 953 954 955 956 957 958 959
    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);
960 961
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_xor_tl(dst, dst, cpu_tmp0);
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
    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);
978 979 980
    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);
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
    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);
998 999
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
1000 1001 1002 1003 1004 1005 1006 1007
    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);
1008 1009
    gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset);
    tcg_gen_and_tl(dst, dst, cpu_tmp0);
1010 1011 1012
    tcg_gen_xori_tl(dst, dst, 0x1);
}

B
blueswir1 已提交
1013
static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
1014
                               target_ulong pc2, TCGv r_cond)
B
bellard 已提交
1015 1016 1017 1018 1019
{
    int l1;

    l1 = gen_new_label();

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

1022
    gen_goto_tb(dc, 0, pc1, pc1 + 4);
B
bellard 已提交
1023 1024

    gen_set_label(l1);
1025
    gen_goto_tb(dc, 1, pc2, pc2 + 4);
B
bellard 已提交
1026 1027
}

B
blueswir1 已提交
1028
static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
1029
                                target_ulong pc2, TCGv r_cond)
B
bellard 已提交
1030 1031 1032 1033 1034
{
    int l1;

    l1 = gen_new_label();

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

1037
    gen_goto_tb(dc, 0, pc2, pc1);
B
bellard 已提交
1038 1039

    gen_set_label(l1);
1040
    gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
B
bellard 已提交
1041 1042
}

1043 1044
static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2,
                                      TCGv r_cond)
B
bellard 已提交
1045 1046 1047 1048 1049
{
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
1050

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

B
blueswir1 已提交
1053
    tcg_gen_movi_tl(cpu_npc, npc1);
B
blueswir1 已提交
1054
    tcg_gen_br(l2);
B
bellard 已提交
1055 1056

    gen_set_label(l1);
B
blueswir1 已提交
1057
    tcg_gen_movi_tl(cpu_npc, npc2);
B
bellard 已提交
1058 1059 1060
    gen_set_label(l2);
}

1061 1062 1063
/* 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 已提交
1064 1065
{
    if (dc->npc == JUMP_PC) {
1066
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
B
bellard 已提交
1067 1068 1069 1070
        dc->npc = DYNAMIC_PC;
    }
}

1071
static inline void save_npc(DisasContext *dc, TCGv cond)
B
bellard 已提交
1072 1073
{
    if (dc->npc == JUMP_PC) {
1074
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
B
bellard 已提交
1075 1076
        dc->npc = DYNAMIC_PC;
    } else if (dc->npc != DYNAMIC_PC) {
B
blueswir1 已提交
1077
        tcg_gen_movi_tl(cpu_npc, dc->npc);
B
bellard 已提交
1078 1079 1080
    }
}

1081
static inline void save_state(DisasContext *dc, TCGv cond)
B
bellard 已提交
1082
{
B
blueswir1 已提交
1083
    tcg_gen_movi_tl(cpu_pc, dc->pc);
1084 1085 1086 1087 1088
    /* flush pending conditional evaluations before exposing cpu state */
    if (dc->cc_op != CC_OP_FLAGS) {
        dc->cc_op = CC_OP_FLAGS;
        gen_helper_compute_psr();
    }
1089
    save_npc(dc, cond);
B
bellard 已提交
1090 1091
}

1092
static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond)
B
bellard 已提交
1093 1094
{
    if (dc->npc == JUMP_PC) {
1095
        gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
B
blueswir1 已提交
1096
        tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
bellard 已提交
1097 1098
        dc->pc = DYNAMIC_PC;
    } else if (dc->npc == DYNAMIC_PC) {
B
blueswir1 已提交
1099
        tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
bellard 已提交
1100 1101 1102 1103 1104 1105
        dc->pc = DYNAMIC_PC;
    } else {
        dc->pc = dc->npc;
    }
}

1106 1107
static inline void gen_op_next_insn(void)
{
B
blueswir1 已提交
1108 1109
    tcg_gen_mov_tl(cpu_pc, cpu_npc);
    tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
1110 1111
}

1112 1113
static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
                            DisasContext *dc)
1114
{
P
pbrook 已提交
1115
    TCGv_i32 r_src;
B
bellard 已提交
1116 1117

#ifdef TARGET_SPARC64
1118
    if (cc)
1119
        r_src = cpu_xcc;
1120
    else
1121
        r_src = cpu_psr;
B
bellard 已提交
1122
#else
1123
    r_src = cpu_psr;
B
bellard 已提交
1124
#endif
1125 1126 1127 1128 1129 1130 1131 1132
    switch (dc->cc_op) {
    case CC_OP_FLAGS:
        break;
    default:
        gen_helper_compute_psr();
        dc->cc_op = CC_OP_FLAGS;
        break;
    }
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
    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;
    }
}
1184

1185
static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
1186
{
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
    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 已提交
1210
        gen_op_eval_fbne(r_dst, cpu_fsr, offset);
1211 1212
        break;
    case 0x2:
B
blueswir1 已提交
1213
        gen_op_eval_fblg(r_dst, cpu_fsr, offset);
1214 1215
        break;
    case 0x3:
B
blueswir1 已提交
1216
        gen_op_eval_fbul(r_dst, cpu_fsr, offset);
1217 1218
        break;
    case 0x4:
B
blueswir1 已提交
1219
        gen_op_eval_fbl(r_dst, cpu_fsr, offset);
1220 1221
        break;
    case 0x5:
B
blueswir1 已提交
1222
        gen_op_eval_fbug(r_dst, cpu_fsr, offset);
1223 1224
        break;
    case 0x6:
B
blueswir1 已提交
1225
        gen_op_eval_fbg(r_dst, cpu_fsr, offset);
1226 1227
        break;
    case 0x7:
B
blueswir1 已提交
1228
        gen_op_eval_fbu(r_dst, cpu_fsr, offset);
1229 1230 1231 1232 1233
        break;
    case 0x8:
        gen_op_eval_ba(r_dst);
        break;
    case 0x9:
B
blueswir1 已提交
1234
        gen_op_eval_fbe(r_dst, cpu_fsr, offset);
1235 1236
        break;
    case 0xa:
B
blueswir1 已提交
1237
        gen_op_eval_fbue(r_dst, cpu_fsr, offset);
1238 1239
        break;
    case 0xb:
B
blueswir1 已提交
1240
        gen_op_eval_fbge(r_dst, cpu_fsr, offset);
1241 1242
        break;
    case 0xc:
B
blueswir1 已提交
1243
        gen_op_eval_fbuge(r_dst, cpu_fsr, offset);
1244 1245
        break;
    case 0xd:
B
blueswir1 已提交
1246
        gen_op_eval_fble(r_dst, cpu_fsr, offset);
1247 1248
        break;
    case 0xe:
B
blueswir1 已提交
1249
        gen_op_eval_fbule(r_dst, cpu_fsr, offset);
1250 1251
        break;
    case 0xf:
B
blueswir1 已提交
1252
        gen_op_eval_fbo(r_dst, cpu_fsr, offset);
1253 1254
        break;
    }
1255
}
1256

1257
#ifdef TARGET_SPARC64
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
// 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,
};
1269

1270
static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
1271 1272 1273 1274
{
    int l1;

    l1 = gen_new_label();
1275
    tcg_gen_movi_tl(r_dst, 0);
P
pbrook 已提交
1276
    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], r_src, 0, l1);
1277 1278 1279
    tcg_gen_movi_tl(r_dst, 1);
    gen_set_label(l1);
}
B
bellard 已提交
1280
#endif
1281

B
bellard 已提交
1282
/* XXX: potentially incorrect if dynamic npc */
1283 1284
static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
                      TCGv r_cond)
1285
{
1286
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1287
    target_ulong target = dc->pc + offset;
1288

1289
    if (cond == 0x0) {
B
blueswir1 已提交
1290 1291 1292 1293 1294 1295 1296 1297
        /* 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;
        }
1298
    } else if (cond == 0x8) {
B
blueswir1 已提交
1299 1300 1301 1302 1303 1304 1305
        /* unconditional taken */
        if (a) {
            dc->pc = target;
            dc->npc = dc->pc + 4;
        } else {
            dc->pc = dc->npc;
            dc->npc = target;
1306
            tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
blueswir1 已提交
1307
        }
1308
    } else {
1309
        flush_cond(dc, r_cond);
1310
        gen_cond(r_cond, cc, cond, dc);
B
blueswir1 已提交
1311
        if (a) {
1312
            gen_branch_a(dc, target, dc->npc, r_cond);
1313
            dc->is_br = 1;
B
blueswir1 已提交
1314
        } else {
1315
            dc->pc = dc->npc;
B
bellard 已提交
1316 1317 1318
            dc->jump_pc[0] = target;
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
B
blueswir1 已提交
1319
        }
1320
    }
1321 1322
}

B
bellard 已提交
1323
/* XXX: potentially incorrect if dynamic npc */
1324 1325
static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
                      TCGv r_cond)
1326 1327
{
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1328 1329
    target_ulong target = dc->pc + offset;

1330
    if (cond == 0x0) {
B
blueswir1 已提交
1331 1332 1333 1334 1335 1336 1337 1338
        /* 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;
        }
1339
    } else if (cond == 0x8) {
B
blueswir1 已提交
1340 1341 1342 1343 1344 1345 1346
        /* unconditional taken */
        if (a) {
            dc->pc = target;
            dc->npc = dc->pc + 4;
        } else {
            dc->pc = dc->npc;
            dc->npc = target;
1347
            tcg_gen_mov_tl(cpu_pc, cpu_npc);
B
blueswir1 已提交
1348
        }
1349
    } else {
1350 1351
        flush_cond(dc, r_cond);
        gen_fcond(r_cond, cc, cond);
B
blueswir1 已提交
1352
        if (a) {
1353
            gen_branch_a(dc, target, dc->npc, r_cond);
1354
            dc->is_br = 1;
B
blueswir1 已提交
1355
        } else {
1356 1357 1358 1359
            dc->pc = dc->npc;
            dc->jump_pc[0] = target;
            dc->jump_pc[1] = dc->npc + 4;
            dc->npc = JUMP_PC;
B
blueswir1 已提交
1360
        }
1361 1362 1363
    }
}

B
bellard 已提交
1364 1365
#ifdef TARGET_SPARC64
/* XXX: potentially incorrect if dynamic npc */
1366 1367
static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
                          TCGv r_cond, TCGv r_reg)
1368
{
B
bellard 已提交
1369 1370 1371
    unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
    target_ulong target = dc->pc + offset;

1372 1373
    flush_cond(dc, r_cond);
    gen_cond_reg(r_cond, cond, r_reg);
B
bellard 已提交
1374
    if (a) {
1375
        gen_branch_a(dc, target, dc->npc, r_cond);
B
blueswir1 已提交
1376
        dc->is_br = 1;
B
bellard 已提交
1377
    } else {
B
blueswir1 已提交
1378 1379 1380 1381
        dc->pc = dc->npc;
        dc->jump_pc[0] = target;
        dc->jump_pc[1] = dc->npc + 4;
        dc->npc = JUMP_PC;
B
bellard 已提交
1382
    }
1383 1384
}

P
pbrook 已提交
1385
static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1386
{
B
blueswir1 已提交
1387 1388
    switch (fccno) {
    case 0:
P
pbrook 已提交
1389
        gen_helper_fcmps(r_rs1, r_rs2);
B
blueswir1 已提交
1390 1391
        break;
    case 1:
P
pbrook 已提交
1392
        gen_helper_fcmps_fcc1(r_rs1, r_rs2);
B
blueswir1 已提交
1393 1394
        break;
    case 2:
P
pbrook 已提交
1395
        gen_helper_fcmps_fcc2(r_rs1, r_rs2);
B
blueswir1 已提交
1396 1397
        break;
    case 3:
P
pbrook 已提交
1398
        gen_helper_fcmps_fcc3(r_rs1, r_rs2);
B
blueswir1 已提交
1399 1400
        break;
    }
1401 1402 1403 1404
}

static inline void gen_op_fcmpd(int fccno)
{
P
pbrook 已提交
1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
    switch (fccno) {
    case 0:
        gen_helper_fcmpd();
        break;
    case 1:
        gen_helper_fcmpd_fcc1();
        break;
    case 2:
        gen_helper_fcmpd_fcc2();
        break;
    case 3:
        gen_helper_fcmpd_fcc3();
        break;
    }
1419 1420 1421 1422
}

static inline void gen_op_fcmpq(int fccno)
{
P
pbrook 已提交
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
    switch (fccno) {
    case 0:
        gen_helper_fcmpq();
        break;
    case 1:
        gen_helper_fcmpq_fcc1();
        break;
    case 2:
        gen_helper_fcmpq_fcc2();
        break;
    case 3:
        gen_helper_fcmpq_fcc3();
        break;
    }
1437 1438
}

P
pbrook 已提交
1439
static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1440
{
B
blueswir1 已提交
1441 1442
    switch (fccno) {
    case 0:
P
pbrook 已提交
1443
        gen_helper_fcmpes(r_rs1, r_rs2);
B
blueswir1 已提交
1444 1445
        break;
    case 1:
P
pbrook 已提交
1446
        gen_helper_fcmpes_fcc1(r_rs1, r_rs2);
B
blueswir1 已提交
1447 1448
        break;
    case 2:
P
pbrook 已提交
1449
        gen_helper_fcmpes_fcc2(r_rs1, r_rs2);
B
blueswir1 已提交
1450 1451
        break;
    case 3:
P
pbrook 已提交
1452
        gen_helper_fcmpes_fcc3(r_rs1, r_rs2);
B
blueswir1 已提交
1453 1454
        break;
    }
1455 1456 1457 1458
}

static inline void gen_op_fcmped(int fccno)
{
P
pbrook 已提交
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
    switch (fccno) {
    case 0:
        gen_helper_fcmped();
        break;
    case 1:
        gen_helper_fcmped_fcc1();
        break;
    case 2:
        gen_helper_fcmped_fcc2();
        break;
    case 3:
        gen_helper_fcmped_fcc3();
        break;
    }
1473 1474 1475 1476
}

static inline void gen_op_fcmpeq(int fccno)
{
P
pbrook 已提交
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
    switch (fccno) {
    case 0:
        gen_helper_fcmpeq();
        break;
    case 1:
        gen_helper_fcmpeq_fcc1();
        break;
    case 2:
        gen_helper_fcmpeq_fcc2();
        break;
    case 3:
        gen_helper_fcmpeq_fcc3();
        break;
    }
1491 1492 1493 1494
}

#else

B
blueswir1 已提交
1495
static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
1496
{
P
pbrook 已提交
1497
    gen_helper_fcmps(r_rs1, r_rs2);
1498 1499 1500 1501
}

static inline void gen_op_fcmpd(int fccno)
{
P
pbrook 已提交
1502
    gen_helper_fcmpd();
1503 1504 1505 1506
}

static inline void gen_op_fcmpq(int fccno)
{
P
pbrook 已提交
1507
    gen_helper_fcmpq();
1508 1509
}

B
blueswir1 已提交
1510
static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
1511
{
P
pbrook 已提交
1512
    gen_helper_fcmpes(r_rs1, r_rs2);
1513 1514 1515 1516
}

static inline void gen_op_fcmped(int fccno)
{
P
pbrook 已提交
1517
    gen_helper_fcmped();
1518 1519 1520 1521
}

static inline void gen_op_fcmpeq(int fccno)
{
P
pbrook 已提交
1522
    gen_helper_fcmpeq();
1523 1524 1525
}
#endif

B
blueswir1 已提交
1526 1527
static inline void gen_op_fpexception_im(int fsr_flags)
{
P
pbrook 已提交
1528
    TCGv_i32 r_const;
B
blueswir1 已提交
1529

1530
    tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
B
blueswir1 已提交
1531
    tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
B
blueswir1 已提交
1532
    r_const = tcg_const_i32(TT_FP_EXCP);
P
pbrook 已提交
1533 1534
    gen_helper_raise_exception(r_const);
    tcg_temp_free_i32(r_const);
B
blueswir1 已提交
1535 1536
}

1537
static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
B
bellard 已提交
1538 1539 1540
{
#if !defined(CONFIG_USER_ONLY)
    if (!dc->fpu_enabled) {
P
pbrook 已提交
1541
        TCGv_i32 r_const;
B
blueswir1 已提交
1542

1543
        save_state(dc, r_cond);
B
blueswir1 已提交
1544
        r_const = tcg_const_i32(TT_NFPU_INSN);
P
pbrook 已提交
1545 1546
        gen_helper_raise_exception(r_const);
        tcg_temp_free_i32(r_const);
B
bellard 已提交
1547 1548 1549 1550 1551 1552 1553
        dc->is_br = 1;
        return 1;
    }
#endif
    return 0;
}

1554 1555
static inline void gen_op_clear_ieee_excp_and_FTT(void)
{
1556
    tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
1557 1558 1559 1560
}

static inline void gen_clear_float_exceptions(void)
{
P
pbrook 已提交
1561
    gen_helper_clear_float_exceptions();
1562 1563
}

B
blueswir1 已提交
1564 1565
/* asi moves */
#ifdef TARGET_SPARC64
P
pbrook 已提交
1566
static inline TCGv_i32 gen_get_asi(int insn, TCGv r_addr)
B
blueswir1 已提交
1567
{
1568
    int asi;
P
pbrook 已提交
1569
    TCGv_i32 r_asi;
B
blueswir1 已提交
1570 1571

    if (IS_IMM) {
P
pbrook 已提交
1572
        r_asi = tcg_temp_new_i32();
1573
        tcg_gen_mov_i32(r_asi, cpu_asi);
B
blueswir1 已提交
1574 1575
    } else {
        asi = GET_FIELD(insn, 19, 26);
1576
        r_asi = tcg_const_i32(asi);
B
blueswir1 已提交
1577
    }
1578 1579 1580
    return r_asi;
}

B
blueswir1 已提交
1581 1582
static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
                              int sign)
1583
{
P
pbrook 已提交
1584
    TCGv_i32 r_asi, r_size, r_sign;
1585

1586
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1587 1588
    r_size = tcg_const_i32(size);
    r_sign = tcg_const_i32(sign);
P
pbrook 已提交
1589 1590 1591 1592
    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 已提交
1593 1594
}

1595
static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
B
blueswir1 已提交
1596
{
P
pbrook 已提交
1597
    TCGv_i32 r_asi, r_size;
B
blueswir1 已提交
1598

1599
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1600
    r_size = tcg_const_i32(size);
P
pbrook 已提交
1601 1602 1603
    gen_helper_st_asi(addr, src, r_asi, r_size);
    tcg_temp_free_i32(r_size);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1604 1605
}

1606
static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
B
blueswir1 已提交
1607
{
P
pbrook 已提交
1608
    TCGv_i32 r_asi, r_size, r_rd;
B
blueswir1 已提交
1609

1610
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1611 1612
    r_size = tcg_const_i32(size);
    r_rd = tcg_const_i32(rd);
P
pbrook 已提交
1613 1614 1615 1616
    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 已提交
1617 1618
}

1619
static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
B
blueswir1 已提交
1620
{
P
pbrook 已提交
1621
    TCGv_i32 r_asi, r_size, r_rd;
B
blueswir1 已提交
1622

1623
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1624 1625
    r_size = tcg_const_i32(size);
    r_rd = tcg_const_i32(rd);
P
pbrook 已提交
1626 1627 1628 1629
    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 已提交
1630 1631
}

1632
static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
B
blueswir1 已提交
1633
{
P
pbrook 已提交
1634
    TCGv_i32 r_asi, r_size, r_sign;
B
blueswir1 已提交
1635

1636
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1637 1638
    r_size = tcg_const_i32(4);
    r_sign = tcg_const_i32(0);
P
pbrook 已提交
1639 1640 1641 1642 1643
    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 已提交
1644
    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
B
blueswir1 已提交
1645 1646
}

B
blueswir1 已提交
1647
static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
B
blueswir1 已提交
1648
{
P
pbrook 已提交
1649
    TCGv_i32 r_asi, r_rd;
B
blueswir1 已提交
1650

1651
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1652
    r_rd = tcg_const_i32(rd);
P
pbrook 已提交
1653 1654 1655
    gen_helper_ldda_asi(addr, r_asi, r_rd);
    tcg_temp_free_i32(r_rd);
    tcg_temp_free_i32(r_asi);
1656 1657
}

1658
static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
1659
{
P
pbrook 已提交
1660
    TCGv_i32 r_asi, r_size;
1661 1662

    gen_movl_reg_TN(rd + 1, cpu_tmp0);
1663
    tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
1664
    r_asi = gen_get_asi(insn, addr);
B
blueswir1 已提交
1665
    r_size = tcg_const_i32(8);
P
pbrook 已提交
1666 1667 1668
    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 已提交
1669 1670
}

B
blueswir1 已提交
1671 1672
static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
                               int rd)
B
blueswir1 已提交
1673
{
P
pbrook 已提交
1674 1675
    TCGv r_val1;
    TCGv_i32 r_asi;
B
blueswir1 已提交
1676

P
pbrook 已提交
1677
    r_val1 = tcg_temp_new();
B
blueswir1 已提交
1678
    gen_movl_reg_TN(rd, r_val1);
1679
    r_asi = gen_get_asi(insn, addr);
P
pbrook 已提交
1680 1681
    gen_helper_cas_asi(dst, addr, r_val1, val2, r_asi);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1682
    tcg_temp_free(r_val1);
B
blueswir1 已提交
1683 1684
}

B
blueswir1 已提交
1685 1686
static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
                                int rd)
B
blueswir1 已提交
1687
{
P
pbrook 已提交
1688
    TCGv_i32 r_asi;
B
blueswir1 已提交
1689

B
blueswir1 已提交
1690
    gen_movl_reg_TN(rd, cpu_tmp64);
1691
    r_asi = gen_get_asi(insn, addr);
P
pbrook 已提交
1692 1693
    gen_helper_casx_asi(dst, addr, cpu_tmp64, val2, r_asi);
    tcg_temp_free_i32(r_asi);
B
blueswir1 已提交
1694 1695 1696 1697
}

#elif !defined(CONFIG_USER_ONLY)

B
blueswir1 已提交
1698 1699
static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
                              int sign)
B
blueswir1 已提交
1700
{
P
pbrook 已提交
1701
    TCGv_i32 r_asi, r_size, r_sign;
B
blueswir1 已提交
1702

B
blueswir1 已提交
1703 1704 1705
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(size);
    r_sign = tcg_const_i32(sign);
P
pbrook 已提交
1706
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
B
blueswir1 已提交
1707 1708 1709
    tcg_temp_free(r_sign);
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
1710
    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
B
blueswir1 已提交
1711 1712
}

1713
static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
B
blueswir1 已提交
1714
{
P
pbrook 已提交
1715
    TCGv_i32 r_asi, r_size;
B
blueswir1 已提交
1716

1717
    tcg_gen_extu_tl_i64(cpu_tmp64, src);
B
blueswir1 已提交
1718 1719
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(size);
P
pbrook 已提交
1720
    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
B
blueswir1 已提交
1721 1722
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
1723 1724
}

1725
static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
B
blueswir1 已提交
1726
{
P
pbrook 已提交
1727 1728
    TCGv_i32 r_asi, r_size, r_sign;
    TCGv_i64 r_val;
B
blueswir1 已提交
1729

B
blueswir1 已提交
1730 1731 1732
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(4);
    r_sign = tcg_const_i32(0);
P
pbrook 已提交
1733
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
B
blueswir1 已提交
1734
    tcg_temp_free(r_sign);
P
pbrook 已提交
1735 1736 1737 1738
    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 已提交
1739 1740
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
1741
    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
B
blueswir1 已提交
1742 1743
}

B
blueswir1 已提交
1744
static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
B
blueswir1 已提交
1745
{
P
pbrook 已提交
1746
    TCGv_i32 r_asi, r_size, r_sign;
B
blueswir1 已提交
1747

B
blueswir1 已提交
1748 1749 1750
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(8);
    r_sign = tcg_const_i32(0);
P
pbrook 已提交
1751
    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
B
blueswir1 已提交
1752 1753 1754
    tcg_temp_free(r_sign);
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
1755 1756
    tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
    gen_movl_TN_reg(rd + 1, cpu_tmp0);
B
blueswir1 已提交
1757
    tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
1758
    tcg_gen_trunc_i64_tl(hi, cpu_tmp64);
B
blueswir1 已提交
1759
    gen_movl_TN_reg(rd, hi);
1760 1761
}

1762
static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
1763
{
P
pbrook 已提交
1764
    TCGv_i32 r_asi, r_size;
1765 1766

    gen_movl_reg_TN(rd + 1, cpu_tmp0);
1767
    tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
B
blueswir1 已提交
1768 1769
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(8);
P
pbrook 已提交
1770
    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
B
blueswir1 已提交
1771 1772
    tcg_temp_free(r_size);
    tcg_temp_free(r_asi);
B
blueswir1 已提交
1773 1774 1775 1776
}
#endif

#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1777
static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
B
blueswir1 已提交
1778
{
P
pbrook 已提交
1779 1780
    TCGv_i64 r_val;
    TCGv_i32 r_asi, r_size;
B
blueswir1 已提交
1781

1782
    gen_ld_asi(dst, addr, insn, 1, 0);
B
blueswir1 已提交
1783

B
blueswir1 已提交
1784 1785 1786
    r_val = tcg_const_i64(0xffULL);
    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
    r_size = tcg_const_i32(1);
P
pbrook 已提交
1787 1788 1789 1790
    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 已提交
1791 1792 1793
}
#endif

1794 1795 1796 1797 1798 1799
static inline TCGv get_src1(unsigned int insn, TCGv def)
{
    TCGv r_rs1 = def;
    unsigned int rs1;

    rs1 = GET_FIELD(insn, 13, 17);
1800 1801 1802
    if (rs1 == 0) {
        tcg_gen_movi_tl(def, 0);
    } else if (rs1 < 8) {
1803
        r_rs1 = cpu_gregs[rs1];
1804
    } else {
1805
        tcg_gen_ld_tl(def, cpu_regwptr, (rs1 - 8) * sizeof(target_ulong));
1806
    }
1807 1808 1809
    return r_rs1;
}

B
blueswir1 已提交
1810 1811 1812 1813 1814
static inline TCGv get_src2(unsigned int insn, TCGv def)
{
    TCGv r_rs2 = def;

    if (IS_IMM) { /* immediate */
1815 1816
        target_long simm = GET_FIELDs(insn, 19, 31);
        tcg_gen_movi_tl(def, simm);
B
blueswir1 已提交
1817
    } else { /* register */
1818 1819 1820 1821
        unsigned int rs2 = GET_FIELD(insn, 27, 31);
        if (rs2 == 0) {
            tcg_gen_movi_tl(def, 0);
        } else if (rs2 < 8) {
B
blueswir1 已提交
1822
            r_rs2 = cpu_gregs[rs2];
1823
        } else {
B
blueswir1 已提交
1824
            tcg_gen_ld_tl(def, cpu_regwptr, (rs2 - 8) * sizeof(target_ulong));
1825
        }
B
blueswir1 已提交
1826 1827 1828 1829
    }
    return r_rs2;
}

1830 1831 1832
#ifdef TARGET_SPARC64
static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
{
1833
    TCGv_i32 r_tl = tcg_temp_new_i32();
1834 1835

    /* load env->tl into r_tl */
1836
    tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
1837 1838

    /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
1839
    tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
1840 1841

    /* calculate offset to current trap state from env->ts, reuse r_tl */
1842
    tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
1843 1844 1845
    tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUState, ts));

    /* tsptr = env->ts[env->tl & MAXTL_MASK] */
1846 1847 1848 1849
    {
        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);
1850
        tcg_temp_free_ptr(r_tl_tmp);
1851
    }
1852

1853
    tcg_temp_free_i32(r_tl);
1854 1855 1856
}
#endif

B
blueswir1 已提交
1857
#define CHECK_IU_FEATURE(dc, FEATURE)                      \
1858
    if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
B
blueswir1 已提交
1859 1860
        goto illegal_insn;
#define CHECK_FPU_FEATURE(dc, FEATURE)                     \
1861
    if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
B
blueswir1 已提交
1862 1863
        goto nfpu_insn;

B
bellard 已提交
1864
/* before an instruction, dc->pc must be static */
1865 1866 1867
static void disas_sparc_insn(DisasContext * dc)
{
    unsigned int insn, opc, rs1, rs2, rd;
1868
    TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
B
Blue Swirl 已提交
1869
    target_long simm;
1870

1871
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
B
blueswir1 已提交
1872
        tcg_gen_debug_insn_start(dc->pc);
B
bellard 已提交
1873
    insn = ldl_code(dc->pc);
1874
    opc = GET_FIELD(insn, 0, 1);
1875

1876
    rd = GET_FIELD(insn, 2, 6);
1877

1878 1879
    cpu_tmp1 = cpu_src1 = tcg_temp_new();
    cpu_tmp2 = cpu_src2 = tcg_temp_new();
1880

1881
    switch (opc) {
B
blueswir1 已提交
1882 1883 1884 1885 1886
    case 0:                     /* branches/sethi */
        {
            unsigned int xop = GET_FIELD(insn, 7, 9);
            int32_t target;
            switch (xop) {
B
bellard 已提交
1887
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1888 1889 1890 1891 1892 1893 1894 1895 1896
            case 0x1:           /* V9 BPcc */
                {
                    int cc;

                    target = GET_FIELD_SP(insn, 0, 18);
                    target = sign_extend(target, 18);
                    target <<= 2;
                    cc = GET_FIELD_SP(insn, 20, 21);
                    if (cc == 0)
1897
                        do_branch(dc, target, insn, 0, cpu_cond);
B
blueswir1 已提交
1898
                    else if (cc == 2)
1899
                        do_branch(dc, target, insn, 1, cpu_cond);
B
blueswir1 已提交
1900 1901 1902 1903 1904 1905 1906
                    else
                        goto illegal_insn;
                    goto jmp_insn;
                }
            case 0x3:           /* V9 BPr */
                {
                    target = GET_FIELD_SP(insn, 0, 13) |
1907
                        (GET_FIELD_SP(insn, 20, 21) << 14);
B
blueswir1 已提交
1908 1909
                    target = sign_extend(target, 16);
                    target <<= 2;
1910
                    cpu_src1 = get_src1(insn, cpu_src1);
1911
                    do_branch_reg(dc, target, insn, cpu_cond, cpu_src1);
B
blueswir1 已提交
1912 1913 1914 1915 1916
                    goto jmp_insn;
                }
            case 0x5:           /* V9 FBPcc */
                {
                    int cc = GET_FIELD_SP(insn, 20, 21);
1917
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
1918
                        goto jmp_insn;
B
blueswir1 已提交
1919 1920 1921
                    target = GET_FIELD_SP(insn, 0, 18);
                    target = sign_extend(target, 19);
                    target <<= 2;
1922
                    do_fbranch(dc, target, insn, cc, cpu_cond);
B
blueswir1 已提交
1923 1924
                    goto jmp_insn;
                }
1925
#else
B
blueswir1 已提交
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
            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;
1936
                    do_branch(dc, target, insn, 0, cpu_cond);
B
blueswir1 已提交
1937 1938 1939 1940
                    goto jmp_insn;
                }
            case 0x6:           /* FBN+x */
                {
1941
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
1942
                        goto jmp_insn;
B
blueswir1 已提交
1943 1944 1945
                    target = GET_FIELD(insn, 10, 31);
                    target = sign_extend(target, 22);
                    target <<= 2;
1946
                    do_fbranch(dc, target, insn, 0, cpu_cond);
B
blueswir1 已提交
1947 1948 1949 1950 1951
                    goto jmp_insn;
                }
            case 0x4:           /* SETHI */
                if (rd) { // nop
                    uint32_t value = GET_FIELD(insn, 10, 31);
B
blueswir1 已提交
1952 1953 1954 1955 1956
                    TCGv r_const;

                    r_const = tcg_const_tl(value << 10);
                    gen_movl_TN_reg(rd, r_const);
                    tcg_temp_free(r_const);
B
blueswir1 已提交
1957 1958 1959 1960
                }
                break;
            case 0x0:           /* UNIMPL */
            default:
B
bellard 已提交
1961
                goto illegal_insn;
B
blueswir1 已提交
1962 1963 1964 1965
            }
            break;
        }
        break;
B
Blue Swirl 已提交
1966 1967
    case 1:                     /*CALL*/
        {
B
blueswir1 已提交
1968
            target_long target = GET_FIELDs(insn, 2, 31) << 2;
B
blueswir1 已提交
1969
            TCGv r_const;
1970

B
blueswir1 已提交
1971 1972 1973
            r_const = tcg_const_tl(dc->pc);
            gen_movl_TN_reg(15, r_const);
            tcg_temp_free(r_const);
B
blueswir1 已提交
1974
            target += dc->pc;
1975
            gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
1976 1977 1978 1979 1980 1981 1982
            dc->npc = target;
        }
        goto jmp_insn;
    case 2:                     /* FPU & Logical Operations */
        {
            unsigned int xop = GET_FIELD(insn, 7, 12);
            if (xop == 0x3a) {  /* generate trap */
1983
                int cond;
B
bellard 已提交
1984

1985
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
1986 1987
                if (IS_IMM) {
                    rs2 = GET_FIELD(insn, 25, 31);
1988
                    tcg_gen_addi_tl(cpu_dst, cpu_src1, rs2);
1989 1990
                } else {
                    rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
1991
                    if (rs2 != 0) {
1992 1993
                        gen_movl_reg_TN(rs2, cpu_src2);
                        tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
1994 1995
                    } else
                        tcg_gen_mov_tl(cpu_dst, cpu_src1);
1996 1997 1998
                }
                cond = GET_FIELD(insn, 3, 6);
                if (cond == 0x8) {
1999
                    save_state(dc, cpu_cond);
B
blueswir1 已提交
2000 2001 2002 2003 2004 2005
                    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 已提交
2006 2007
                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
                    gen_helper_raise_exception(cpu_tmp32);
2008
                } else if (cond != 0) {
P
pbrook 已提交
2009
                    TCGv r_cond = tcg_temp_new();
B
blueswir1 已提交
2010
                    int l1;
B
bellard 已提交
2011
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2012 2013
                    /* V9 icc/xcc */
                    int cc = GET_FIELD_SP(insn, 11, 12);
B
blueswir1 已提交
2014

2015
                    save_state(dc, cpu_cond);
B
blueswir1 已提交
2016
                    if (cc == 0)
2017
                        gen_cond(r_cond, 0, cond, dc);
B
blueswir1 已提交
2018
                    else if (cc == 2)
2019
                        gen_cond(r_cond, 1, cond, dc);
B
blueswir1 已提交
2020 2021
                    else
                        goto illegal_insn;
B
bellard 已提交
2022
#else
2023
                    save_state(dc, cpu_cond);
2024
                    gen_cond(r_cond, 0, cond, dc);
B
bellard 已提交
2025
#endif
B
blueswir1 已提交
2026 2027 2028 2029 2030 2031 2032 2033 2034
                    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 已提交
2035 2036
                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
                    gen_helper_raise_exception(cpu_tmp32);
B
blueswir1 已提交
2037 2038

                    gen_set_label(l1);
B
blueswir1 已提交
2039
                    tcg_temp_free(r_cond);
2040
                }
B
bellard 已提交
2041
                gen_op_next_insn();
B
bellard 已提交
2042
                tcg_gen_exit_tb(0);
B
bellard 已提交
2043 2044
                dc->is_br = 1;
                goto jmp_insn;
2045 2046 2047 2048
            } else if (xop == 0x28) {
                rs1 = GET_FIELD(insn, 13, 17);
                switch(rs1) {
                case 0: /* rdy */
2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
#ifndef TARGET_SPARC64
                case 0x01 ... 0x0e: /* undefined in the SPARCv8
                                       manual, rdy on the microSPARC
                                       II */
                case 0x0f:          /* stbar in the SPARCv8 manual,
                                       rdy on the microSPARC II */
                case 0x10 ... 0x1f: /* implementation-dependent in the
                                       SPARCv8 manual, rdy on the
                                       microSPARC II */
#endif
2059
                    gen_movl_TN_reg(rd, cpu_y);
2060
                    break;
B
bellard 已提交
2061
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2062
                case 0x2: /* V9 rdccr */
2063
                    gen_helper_compute_psr();
P
pbrook 已提交
2064
                    gen_helper_rdccr(cpu_dst);
2065
                    gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2066
                    break;
B
blueswir1 已提交
2067
                case 0x3: /* V9 rdasi */
2068
                    tcg_gen_ext_i32_tl(cpu_dst, cpu_asi);
2069
                    gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2070
                    break;
B
blueswir1 已提交
2071
                case 0x4: /* V9 rdtick */
B
blueswir1 已提交
2072
                    {
P
pbrook 已提交
2073
                        TCGv_ptr r_tickptr;
B
blueswir1 已提交
2074

P
pbrook 已提交
2075
                        r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
2076 2077
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, tick));
P
pbrook 已提交
2078 2079
                        gen_helper_tick_get_count(cpu_dst, r_tickptr);
                        tcg_temp_free_ptr(r_tickptr);
2080
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2081
                    }
B
bellard 已提交
2082
                    break;
B
blueswir1 已提交
2083
                case 0x5: /* V9 rdpc */
B
blueswir1 已提交
2084 2085 2086 2087 2088 2089 2090
                    {
                        TCGv r_const;

                        r_const = tcg_const_tl(dc->pc);
                        gen_movl_TN_reg(rd, r_const);
                        tcg_temp_free(r_const);
                    }
B
blueswir1 已提交
2091 2092
                    break;
                case 0x6: /* V9 rdfprs */
2093
                    tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
2094
                    gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2095
                    break;
2096 2097
                case 0xf: /* V9 membar */
                    break; /* no effect */
B
blueswir1 已提交
2098
                case 0x13: /* Graphics Status */
2099
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2100
                        goto jmp_insn;
2101
                    gen_movl_TN_reg(rd, cpu_gsr);
B
bellard 已提交
2102
                    break;
2103 2104 2105 2106
                case 0x16: /* Softint */
                    tcg_gen_ext_i32_tl(cpu_dst, cpu_softint);
                    gen_movl_TN_reg(rd, cpu_dst);
                    break;
B
blueswir1 已提交
2107
                case 0x17: /* Tick compare */
2108
                    gen_movl_TN_reg(rd, cpu_tick_cmpr);
B
bellard 已提交
2109
                    break;
B
blueswir1 已提交
2110
                case 0x18: /* System tick */
B
blueswir1 已提交
2111
                    {
P
pbrook 已提交
2112
                        TCGv_ptr r_tickptr;
B
blueswir1 已提交
2113

P
pbrook 已提交
2114
                        r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
2115 2116
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, stick));
P
pbrook 已提交
2117 2118
                        gen_helper_tick_get_count(cpu_dst, r_tickptr);
                        tcg_temp_free_ptr(r_tickptr);
2119
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2120
                    }
B
bellard 已提交
2121
                    break;
B
blueswir1 已提交
2122
                case 0x19: /* System tick compare */
2123
                    gen_movl_TN_reg(rd, cpu_stick_cmpr);
B
bellard 已提交
2124
                    break;
B
blueswir1 已提交
2125 2126 2127 2128 2129
                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 已提交
2130 2131
#endif
                default:
2132 2133
                    goto illegal_insn;
                }
2134
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
2135
            } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
B
bellard 已提交
2136
#ifndef TARGET_SPARC64
B
blueswir1 已提交
2137 2138
                if (!supervisor(dc))
                    goto priv_insn;
2139 2140
                gen_helper_compute_psr();
                dc->cc_op = CC_OP_FLAGS;
P
pbrook 已提交
2141
                gen_helper_rdpsr(cpu_dst);
B
blueswir1 已提交
2142
#else
2143
                CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
                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
2155
                    tcg_gen_mov_tl(cpu_dst, cpu_hintp);
B
blueswir1 已提交
2156 2157
                    break;
                case 5: // htba
2158
                    tcg_gen_mov_tl(cpu_dst, cpu_htba);
B
blueswir1 已提交
2159 2160
                    break;
                case 6: // hver
2161
                    tcg_gen_mov_tl(cpu_dst, cpu_hver);
B
blueswir1 已提交
2162 2163
                    break;
                case 31: // hstick_cmpr
2164
                    tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
B
blueswir1 已提交
2165 2166 2167 2168 2169
                    break;
                default:
                    goto illegal_insn;
                }
#endif
2170
                gen_movl_TN_reg(rd, cpu_dst);
2171
                break;
B
bellard 已提交
2172
            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
B
blueswir1 已提交
2173 2174
                if (!supervisor(dc))
                    goto priv_insn;
B
bellard 已提交
2175 2176
#ifdef TARGET_SPARC64
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2177 2178
                switch (rs1) {
                case 0: // tpc
2179
                    {
P
pbrook 已提交
2180
                        TCGv_ptr r_tsptr;
2181

P
pbrook 已提交
2182
                        r_tsptr = tcg_temp_new_ptr();
2183
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
P
pbrook 已提交
2184
                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2185
                                      offsetof(trap_state, tpc));
P
pbrook 已提交
2186
                        tcg_temp_free_ptr(r_tsptr);
2187
                    }
B
blueswir1 已提交
2188 2189
                    break;
                case 1: // tnpc
2190
                    {
P
pbrook 已提交
2191
                        TCGv_ptr r_tsptr;
2192

P
pbrook 已提交
2193
                        r_tsptr = tcg_temp_new_ptr();
2194
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
2195
                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2196
                                      offsetof(trap_state, tnpc));
P
pbrook 已提交
2197
                        tcg_temp_free_ptr(r_tsptr);
2198
                    }
B
blueswir1 已提交
2199 2200
                    break;
                case 2: // tstate
2201
                    {
P
pbrook 已提交
2202
                        TCGv_ptr r_tsptr;
2203

P
pbrook 已提交
2204
                        r_tsptr = tcg_temp_new_ptr();
2205
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
2206
                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2207
                                      offsetof(trap_state, tstate));
P
pbrook 已提交
2208
                        tcg_temp_free_ptr(r_tsptr);
2209
                    }
B
blueswir1 已提交
2210 2211
                    break;
                case 3: // tt
2212
                    {
P
pbrook 已提交
2213
                        TCGv_ptr r_tsptr;
2214

P
pbrook 已提交
2215
                        r_tsptr = tcg_temp_new_ptr();
2216
                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
P
pbrook 已提交
2217
                        tcg_gen_ld_i32(cpu_tmp32, r_tsptr,
2218
                                       offsetof(trap_state, tt));
P
pbrook 已提交
2219 2220
                        tcg_temp_free_ptr(r_tsptr);
                        tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
2221
                    }
B
blueswir1 已提交
2222 2223
                    break;
                case 4: // tick
B
blueswir1 已提交
2224
                    {
P
pbrook 已提交
2225
                        TCGv_ptr r_tickptr;
B
blueswir1 已提交
2226

P
pbrook 已提交
2227
                        r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
2228 2229
                        tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                       offsetof(CPUState, tick));
P
pbrook 已提交
2230
                        gen_helper_tick_get_count(cpu_tmp0, r_tickptr);
2231
                        gen_movl_TN_reg(rd, cpu_tmp0);
P
pbrook 已提交
2232
                        tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
2233
                    }
B
blueswir1 已提交
2234 2235
                    break;
                case 5: // tba
2236
                    tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
B
blueswir1 已提交
2237 2238
                    break;
                case 6: // pstate
B
blueswir1 已提交
2239 2240
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, pstate));
2241
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2242 2243
                    break;
                case 7: // tl
B
blueswir1 已提交
2244 2245
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, tl));
2246
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2247 2248
                    break;
                case 8: // pil
B
blueswir1 已提交
2249 2250
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, psrpil));
2251
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2252 2253
                    break;
                case 9: // cwp
P
pbrook 已提交
2254
                    gen_helper_rdcwp(cpu_tmp0);
B
blueswir1 已提交
2255 2256
                    break;
                case 10: // cansave
B
blueswir1 已提交
2257 2258
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, cansave));
2259
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2260 2261
                    break;
                case 11: // canrestore
B
blueswir1 已提交
2262 2263
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, canrestore));
2264
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2265 2266
                    break;
                case 12: // cleanwin
B
blueswir1 已提交
2267 2268
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, cleanwin));
2269
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2270 2271
                    break;
                case 13: // otherwin
B
blueswir1 已提交
2272 2273
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, otherwin));
2274
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2275 2276
                    break;
                case 14: // wstate
B
blueswir1 已提交
2277 2278
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, wstate));
2279
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2280
                    break;
B
blueswir1 已提交
2281
                case 16: // UA2005 gl
2282
                    CHECK_IU_FEATURE(dc, GL);
B
blueswir1 已提交
2283 2284
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                   offsetof(CPUSPARCState, gl));
2285
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
B
blueswir1 已提交
2286 2287
                    break;
                case 26: // UA2005 strand status
2288
                    CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
2289 2290
                    if (!hypervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
2291
                    tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
B
blueswir1 已提交
2292
                    break;
B
blueswir1 已提交
2293
                case 31: // ver
2294
                    tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
B
blueswir1 已提交
2295 2296 2297 2298 2299
                    break;
                case 15: // fq
                default:
                    goto illegal_insn;
                }
B
bellard 已提交
2300
#else
2301
                tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
B
bellard 已提交
2302
#endif
2303
                gen_movl_TN_reg(rd, cpu_tmp0);
2304
                break;
B
bellard 已提交
2305 2306
            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
2307
                save_state(dc, cpu_cond);
P
pbrook 已提交
2308
                gen_helper_flushw();
B
bellard 已提交
2309
#else
B
blueswir1 已提交
2310 2311
                if (!supervisor(dc))
                    goto priv_insn;
2312
                gen_movl_TN_reg(rd, cpu_tbr);
B
bellard 已提交
2313
#endif
2314 2315
                break;
#endif
B
blueswir1 已提交
2316
            } else if (xop == 0x34) {   /* FPU Operations */
2317
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2318
                    goto jmp_insn;
B
blueswir1 已提交
2319
                gen_op_clear_ieee_excp_and_FTT();
2320
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2321 2322
                rs2 = GET_FIELD(insn, 27, 31);
                xop = GET_FIELD(insn, 18, 26);
B
Blue Swirl 已提交
2323
                save_state(dc, cpu_cond);
B
blueswir1 已提交
2324
                switch (xop) {
B
Blue Swirl 已提交
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541
                case 0x1: /* fmovs */
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
                    break;
                case 0x5: /* fnegs */
                    gen_helper_fnegs(cpu_fpr[rd], cpu_fpr[rs2]);
                    break;
                case 0x9: /* fabss */
                    gen_helper_fabss(cpu_fpr[rd], cpu_fpr[rs2]);
                    break;
                case 0x29: /* fsqrts */
                    CHECK_FPU_FEATURE(dc, FSQRT);
                    gen_clear_float_exceptions();
                    gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0x2a: /* fsqrtd */
                    CHECK_FPU_FEATURE(dc, FSQRT);
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fsqrtd();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x2b: /* fsqrtq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fsqrtq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0x41: /* fadds */
                    gen_clear_float_exceptions();
                    gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0x42: /* faddd */
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_faddd();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x43: /* faddq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT0(QFPREG(rs1));
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_faddq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0x45: /* fsubs */
                    gen_clear_float_exceptions();
                    gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0x46: /* fsubd */
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fsubd();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x47: /* fsubq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT0(QFPREG(rs1));
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fsubq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0x49: /* fmuls */
                    CHECK_FPU_FEATURE(dc, FMUL);
                    gen_clear_float_exceptions();
                    gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0x4a: /* fmuld */
                    CHECK_FPU_FEATURE(dc, FMUL);
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fmuld();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x4b: /* fmulq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    CHECK_FPU_FEATURE(dc, FMUL);
                    gen_op_load_fpr_QT0(QFPREG(rs1));
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fmulq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0x4d: /* fdivs */
                    gen_clear_float_exceptions();
                    gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0x4e: /* fdivd */
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fdivd();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x4f: /* fdivq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT0(QFPREG(rs1));
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fdivq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0x69: /* fsmuld */
                    CHECK_FPU_FEATURE(dc, FSMULD);
                    gen_clear_float_exceptions();
                    gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x6e: /* fdmulq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fdmulq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0xc4: /* fitos */
                    gen_clear_float_exceptions();
                    gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0xc6: /* fdtos */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fdtos(cpu_tmp32);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0xc7: /* fqtos */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fqtos(cpu_tmp32);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0xc8: /* fitod */
                    gen_helper_fitod(cpu_fpr[rs2]);
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0xc9: /* fstod */
                    gen_helper_fstod(cpu_fpr[rs2]);
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0xcb: /* fqtod */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fqtod();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0xcc: /* fitoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_helper_fitoq(cpu_fpr[rs2]);
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0xcd: /* fstoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_helper_fstoq(cpu_fpr[rs2]);
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0xce: /* fdtoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_helper_fdtoq();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0xd1: /* fstoi */
                    gen_clear_float_exceptions();
                    gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0xd2: /* fdtoi */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fdtoi(cpu_tmp32);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0xd3: /* fqtoi */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fqtoi(cpu_tmp32);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
B
bellard 已提交
2542
#ifdef TARGET_SPARC64
B
Blue Swirl 已提交
2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622
                case 0x2: /* V9 fmovd */
                    tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
                    break;
                case 0x3: /* V9 fmovq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd)], cpu_fpr[QFPREG(rs2)]);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1],
                                    cpu_fpr[QFPREG(rs2) + 1]);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2],
                                    cpu_fpr[QFPREG(rs2) + 2]);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],
                                    cpu_fpr[QFPREG(rs2) + 3]);
                    break;
                case 0x6: /* V9 fnegd */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_helper_fnegd();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x7: /* V9 fnegq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_helper_fnegq();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0xa: /* V9 fabsd */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_helper_fabsd();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0xb: /* V9 fabsq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_helper_fabsq();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
                case 0x81: /* V9 fstox */
                    gen_clear_float_exceptions();
                    gen_helper_fstox(cpu_fpr[rs2]);
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x82: /* V9 fdtox */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fdtox();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x83: /* V9 fqtox */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_QT1(QFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fqtox();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x84: /* V9 fxtos */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fxtos(cpu_tmp32);
                    gen_helper_check_ieee_exceptions();
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                    break;
                case 0x88: /* V9 fxtod */
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fxtod();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_DT0_fpr(DFPREG(rd));
                    break;
                case 0x8c: /* V9 fxtoq */
                    CHECK_FPU_FEATURE(dc, FLOAT128);
                    gen_op_load_fpr_DT1(DFPREG(rs2));
                    gen_clear_float_exceptions();
                    gen_helper_fxtoq();
                    gen_helper_check_ieee_exceptions();
                    gen_op_store_QT0_fpr(QFPREG(rd));
                    break;
B
blueswir1 已提交
2623
#endif
B
Blue Swirl 已提交
2624 2625
                default:
                    goto illegal_insn;
B
blueswir1 已提交
2626 2627
                }
            } else if (xop == 0x35) {   /* FPU Operations */
B
bellard 已提交
2628
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2629
                int cond;
B
bellard 已提交
2630
#endif
2631
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
2632
                    goto jmp_insn;
B
blueswir1 已提交
2633
                gen_op_clear_ieee_excp_and_FTT();
2634
                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2635 2636
                rs2 = GET_FIELD(insn, 27, 31);
                xop = GET_FIELD(insn, 18, 26);
B
Blue Swirl 已提交
2637
                save_state(dc, cpu_cond);
B
bellard 已提交
2638
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2639
                if ((xop & 0x11f) == 0x005) { // V9 fmovsr
B
blueswir1 已提交
2640 2641 2642
                    int l1;

                    l1 = gen_new_label();
B
blueswir1 已提交
2643
                    cond = GET_FIELD_SP(insn, 14, 17);
2644
                    cpu_src1 = get_src1(insn, cpu_src1);
P
pbrook 已提交
2645 2646
                    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                       0, l1);
B
blueswir1 已提交
2647
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
B
blueswir1 已提交
2648
                    gen_set_label(l1);
B
blueswir1 已提交
2649 2650
                    break;
                } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
B
blueswir1 已提交
2651 2652 2653
                    int l1;

                    l1 = gen_new_label();
B
blueswir1 已提交
2654
                    cond = GET_FIELD_SP(insn, 14, 17);
2655
                    cpu_src1 = get_src1(insn, cpu_src1);
P
pbrook 已提交
2656 2657
                    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                       0, l1);
B
blueswir1 已提交
2658 2659
                    tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
2660
                    gen_set_label(l1);
B
blueswir1 已提交
2661 2662
                    break;
                } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
B
blueswir1 已提交
2663 2664
                    int l1;

B
blueswir1 已提交
2665
                    CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2666
                    l1 = gen_new_label();
B
blueswir1 已提交
2667
                    cond = GET_FIELD_SP(insn, 14, 17);
2668
                    cpu_src1 = get_src1(insn, cpu_src1);
P
pbrook 已提交
2669 2670
                    tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                       0, l1);
B
blueswir1 已提交
2671 2672 2673 2674
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd)], cpu_fpr[QFPREG(rs2)]);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1], cpu_fpr[QFPREG(rs2) + 1]);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2], cpu_fpr[QFPREG(rs2) + 2]);
                    tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], cpu_fpr[QFPREG(rs2) + 3]);
B
blueswir1 已提交
2675
                    gen_set_label(l1);
B
blueswir1 已提交
2676
                    break;
B
blueswir1 已提交
2677 2678 2679
                }
#endif
                switch (xop) {
B
bellard 已提交
2680
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2681
#define FMOVSCC(fcc)                                                    \
2682
                    {                                                   \
2683
                        TCGv r_cond;                                    \
2684 2685 2686
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2687
                        r_cond = tcg_temp_new();                        \
2688 2689
                        cond = GET_FIELD_SP(insn, 14, 17);              \
                        gen_fcond(r_cond, fcc, cond);                   \
P
pbrook 已提交
2690 2691
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
B
blueswir1 已提交
2692 2693 2694 2695 2696 2697 2698 2699 2700 2701
                        tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVDCC(fcc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2702
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719
                        cond = GET_FIELD_SP(insn, 14, 17);              \
                        gen_fcond(r_cond, fcc, cond);                   \
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
                        tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)],            \
                                        cpu_fpr[DFPREG(rs2)]);          \
                        tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                        cpu_fpr[DFPREG(rs2) + 1]);      \
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVQCC(fcc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2720
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732
                        cond = GET_FIELD_SP(insn, 14, 17);              \
                        gen_fcond(r_cond, fcc, cond);                   \
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd)],            \
                                        cpu_fpr[QFPREG(rs2)]);          \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1],        \
                                        cpu_fpr[QFPREG(rs2) + 1]);      \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2],        \
                                        cpu_fpr[QFPREG(rs2) + 2]);      \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                        cpu_fpr[QFPREG(rs2) + 3]);      \
2733
                        gen_set_label(l1);                              \
B
blueswir1 已提交
2734
                        tcg_temp_free(r_cond);                          \
2735
                    }
B
blueswir1 已提交
2736
                    case 0x001: /* V9 fmovscc %fcc0 */
B
blueswir1 已提交
2737
                        FMOVSCC(0);
B
blueswir1 已提交
2738 2739
                        break;
                    case 0x002: /* V9 fmovdcc %fcc0 */
B
blueswir1 已提交
2740
                        FMOVDCC(0);
B
blueswir1 已提交
2741 2742
                        break;
                    case 0x003: /* V9 fmovqcc %fcc0 */
B
blueswir1 已提交
2743
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2744
                        FMOVQCC(0);
B
blueswir1 已提交
2745
                        break;
B
blueswir1 已提交
2746
                    case 0x041: /* V9 fmovscc %fcc1 */
B
blueswir1 已提交
2747
                        FMOVSCC(1);
B
blueswir1 已提交
2748 2749
                        break;
                    case 0x042: /* V9 fmovdcc %fcc1 */
B
blueswir1 已提交
2750
                        FMOVDCC(1);
B
blueswir1 已提交
2751 2752
                        break;
                    case 0x043: /* V9 fmovqcc %fcc1 */
B
blueswir1 已提交
2753
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2754
                        FMOVQCC(1);
B
blueswir1 已提交
2755
                        break;
B
blueswir1 已提交
2756
                    case 0x081: /* V9 fmovscc %fcc2 */
B
blueswir1 已提交
2757
                        FMOVSCC(2);
B
blueswir1 已提交
2758 2759
                        break;
                    case 0x082: /* V9 fmovdcc %fcc2 */
B
blueswir1 已提交
2760
                        FMOVDCC(2);
B
blueswir1 已提交
2761 2762
                        break;
                    case 0x083: /* V9 fmovqcc %fcc2 */
B
blueswir1 已提交
2763
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2764
                        FMOVQCC(2);
B
blueswir1 已提交
2765
                        break;
B
blueswir1 已提交
2766
                    case 0x0c1: /* V9 fmovscc %fcc3 */
B
blueswir1 已提交
2767
                        FMOVSCC(3);
B
blueswir1 已提交
2768 2769
                        break;
                    case 0x0c2: /* V9 fmovdcc %fcc3 */
B
blueswir1 已提交
2770
                        FMOVDCC(3);
B
blueswir1 已提交
2771 2772
                        break;
                    case 0x0c3: /* V9 fmovqcc %fcc3 */
B
blueswir1 已提交
2773
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2774
                        FMOVQCC(3);
B
blueswir1 已提交
2775
                        break;
B
blueswir1 已提交
2776 2777 2778 2779 2780 2781 2782 2783 2784
#undef FMOVSCC
#undef FMOVDCC
#undef FMOVQCC
#define FMOVSCC(icc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2785
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2786
                        cond = GET_FIELD_SP(insn, 14, 17);              \
2787
                        gen_cond(r_cond, icc, cond, dc);                \
B
blueswir1 已提交
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
                        tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVDCC(icc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2800
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2801
                        cond = GET_FIELD_SP(insn, 14, 17);              \
2802
                        gen_cond(r_cond, icc, cond, dc);                \
B
blueswir1 已提交
2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
                        tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)],            \
                                        cpu_fpr[DFPREG(rs2)]);          \
                        tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                        cpu_fpr[DFPREG(rs2) + 1]);      \
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
#define FMOVQCC(icc)                                                    \
                    {                                                   \
                        TCGv r_cond;                                    \
                        int l1;                                         \
                                                                        \
                        l1 = gen_new_label();                           \
B
Blue Swirl 已提交
2818
                        r_cond = tcg_temp_new();                        \
B
blueswir1 已提交
2819
                        cond = GET_FIELD_SP(insn, 14, 17);              \
2820
                        gen_cond(r_cond, icc, cond, dc);                \
B
blueswir1 已提交
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833
                        tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                           0, l1);                      \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd)],            \
                                        cpu_fpr[QFPREG(rs2)]);          \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1],        \
                                        cpu_fpr[QFPREG(rs2) + 1]);      \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2],        \
                                        cpu_fpr[QFPREG(rs2) + 2]);      \
                        tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                        cpu_fpr[QFPREG(rs2) + 3]);      \
                        gen_set_label(l1);                              \
                        tcg_temp_free(r_cond);                          \
                    }
2834

B
blueswir1 已提交
2835
                    case 0x101: /* V9 fmovscc %icc */
B
blueswir1 已提交
2836
                        FMOVSCC(0);
B
blueswir1 已提交
2837 2838
                        break;
                    case 0x102: /* V9 fmovdcc %icc */
B
blueswir1 已提交
2839
                        FMOVDCC(0);
B
blueswir1 已提交
2840
                    case 0x103: /* V9 fmovqcc %icc */
B
blueswir1 已提交
2841
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2842
                        FMOVQCC(0);
B
blueswir1 已提交
2843
                        break;
B
blueswir1 已提交
2844
                    case 0x181: /* V9 fmovscc %xcc */
B
blueswir1 已提交
2845
                        FMOVSCC(1);
B
blueswir1 已提交
2846 2847
                        break;
                    case 0x182: /* V9 fmovdcc %xcc */
B
blueswir1 已提交
2848
                        FMOVDCC(1);
B
blueswir1 已提交
2849 2850
                        break;
                    case 0x183: /* V9 fmovqcc %xcc */
B
blueswir1 已提交
2851
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2852
                        FMOVQCC(1);
B
blueswir1 已提交
2853
                        break;
B
blueswir1 已提交
2854 2855 2856
#undef FMOVSCC
#undef FMOVDCC
#undef FMOVQCC
B
blueswir1 已提交
2857 2858
#endif
                    case 0x51: /* fcmps, V9 %fcc */
B
blueswir1 已提交
2859
                        gen_op_fcmps(rd & 3, cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
2860
                        break;
B
blueswir1 已提交
2861
                    case 0x52: /* fcmpd, V9 %fcc */
B
blueswir1 已提交
2862 2863
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
2864
                        gen_op_fcmpd(rd & 3);
B
blueswir1 已提交
2865
                        break;
B
blueswir1 已提交
2866
                    case 0x53: /* fcmpq, V9 %fcc */
B
blueswir1 已提交
2867
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2868 2869
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
2870
                        gen_op_fcmpq(rd & 3);
B
blueswir1 已提交
2871
                        break;
B
blueswir1 已提交
2872
                    case 0x55: /* fcmpes, V9 %fcc */
B
blueswir1 已提交
2873
                        gen_op_fcmpes(rd & 3, cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
2874 2875 2876 2877
                        break;
                    case 0x56: /* fcmped, V9 %fcc */
                        gen_op_load_fpr_DT0(DFPREG(rs1));
                        gen_op_load_fpr_DT1(DFPREG(rs2));
2878
                        gen_op_fcmped(rd & 3);
B
blueswir1 已提交
2879
                        break;
B
blueswir1 已提交
2880
                    case 0x57: /* fcmpeq, V9 %fcc */
B
blueswir1 已提交
2881
                        CHECK_FPU_FEATURE(dc, FLOAT128);
B
blueswir1 已提交
2882 2883
                        gen_op_load_fpr_QT0(QFPREG(rs1));
                        gen_op_load_fpr_QT1(QFPREG(rs2));
2884
                        gen_op_fcmpeq(rd & 3);
B
blueswir1 已提交
2885
                        break;
B
blueswir1 已提交
2886 2887 2888 2889 2890
                    default:
                        goto illegal_insn;
                }
            } else if (xop == 0x2) {
                // clr/mov shortcut
B
bellard 已提交
2891 2892

                rs1 = GET_FIELD(insn, 13, 17);
B
blueswir1 已提交
2893
                if (rs1 == 0) {
B
blueswir1 已提交
2894
                    // or %g0, x, y -> mov T0, x; mov y, T0
B
blueswir1 已提交
2895
                    if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
2896 2897
                        TCGv r_const;

B
Blue Swirl 已提交
2898 2899
                        simm = GET_FIELDs(insn, 19, 31);
                        r_const = tcg_const_tl(simm);
B
blueswir1 已提交
2900 2901
                        gen_movl_TN_reg(rd, r_const);
                        tcg_temp_free(r_const);
B
blueswir1 已提交
2902 2903
                    } else {            /* register */
                        rs2 = GET_FIELD(insn, 27, 31);
2904
                        gen_movl_reg_TN(rs2, cpu_dst);
B
blueswir1 已提交
2905
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2906 2907
                    }
                } else {
2908
                    cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
2909
                    if (IS_IMM) {       /* immediate */
B
Blue Swirl 已提交
2910 2911
                        simm = GET_FIELDs(insn, 19, 31);
                        tcg_gen_ori_tl(cpu_dst, cpu_src1, simm);
B
blueswir1 已提交
2912
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2913 2914 2915 2916
                    } else {            /* register */
                        // or x, %g0, y -> mov T1, x; mov y, T1
                        rs2 = GET_FIELD(insn, 27, 31);
                        if (rs2 != 0) {
2917 2918
                            gen_movl_reg_TN(rs2, cpu_src2);
                            tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
B
blueswir1 已提交
2919
                            gen_movl_TN_reg(rd, cpu_dst);
2920
                        } else
B
blueswir1 已提交
2921
                            gen_movl_TN_reg(rd, cpu_src1);
B
blueswir1 已提交
2922 2923
                    }
                }
B
bellard 已提交
2924
#ifdef TARGET_SPARC64
B
blueswir1 已提交
2925
            } else if (xop == 0x25) { /* sll, V9 sllx */
2926
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
2927
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
2928
                    simm = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
2929
                    if (insn & (1 << 12)) {
B
Blue Swirl 已提交
2930
                        tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
B
blueswir1 已提交
2931
                    } else {
B
Blue Swirl 已提交
2932
                        tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
B
blueswir1 已提交
2933
                    }
B
blueswir1 已提交
2934
                } else {                /* register */
B
bellard 已提交
2935
                    rs2 = GET_FIELD(insn, 27, 31);
2936
                    gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
2937
                    if (insn & (1 << 12)) {
2938
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
B
blueswir1 已提交
2939
                    } else {
2940
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
B
blueswir1 已提交
2941
                    }
B
blueswir1 已提交
2942
                    tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
B
bellard 已提交
2943
                }
2944
                gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2945
            } else if (xop == 0x26) { /* srl, V9 srlx */
2946
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
2947
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
2948
                    simm = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
2949
                    if (insn & (1 << 12)) {
B
Blue Swirl 已提交
2950
                        tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
B
blueswir1 已提交
2951
                    } else {
2952
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
B
Blue Swirl 已提交
2953
                        tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
B
blueswir1 已提交
2954
                    }
B
blueswir1 已提交
2955
                } else {                /* register */
B
bellard 已提交
2956
                    rs2 = GET_FIELD(insn, 27, 31);
2957
                    gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
2958
                    if (insn & (1 << 12)) {
2959 2960
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
                        tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
B
blueswir1 已提交
2961
                    } else {
2962 2963 2964
                        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 已提交
2965
                    }
B
bellard 已提交
2966
                }
2967
                gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
2968
            } else if (xop == 0x27) { /* sra, V9 srax */
2969
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
2970
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
2971
                    simm = GET_FIELDs(insn, 20, 31);
B
blueswir1 已提交
2972
                    if (insn & (1 << 12)) {
B
Blue Swirl 已提交
2973
                        tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
B
blueswir1 已提交
2974
                    } else {
2975
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
B
blueswir1 已提交
2976
                        tcg_gen_ext32s_i64(cpu_dst, cpu_dst);
B
Blue Swirl 已提交
2977
                        tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
B
blueswir1 已提交
2978
                    }
B
blueswir1 已提交
2979
                } else {                /* register */
B
bellard 已提交
2980
                    rs2 = GET_FIELD(insn, 27, 31);
2981
                    gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
2982
                    if (insn & (1 << 12)) {
2983 2984
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
                        tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
B
blueswir1 已提交
2985
                    } else {
2986 2987
                        tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
B
blueswir1 已提交
2988
                        tcg_gen_ext32s_i64(cpu_dst, cpu_dst);
2989
                        tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
B
blueswir1 已提交
2990
                    }
B
bellard 已提交
2991
                }
2992
                gen_movl_TN_reg(rd, cpu_dst);
B
bellard 已提交
2993
#endif
2994
            } else if (xop < 0x36) {
2995
                if (xop < 0x20) {
2996 2997
                    cpu_src1 = get_src1(insn, cpu_src1);
                    cpu_src2 = get_src2(insn, cpu_src2);
2998
                    switch (xop & ~0x10) {
2999
                    case 0x0: /* add */
3000 3001 3002 3003
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            if (xop & 0x10) {
                                gen_op_addi_cc(cpu_dst, cpu_src1, simm);
B
Blue Swirl 已提交
3004 3005
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
                                dc->cc_op = CC_OP_ADD;
3006 3007 3008 3009 3010 3011
                            } 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 已提交
3012 3013
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
                                dc->cc_op = CC_OP_ADD;
3014 3015 3016 3017
                            } else {
                                tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
                            }
                        }
3018
                        break;
3019
                    case 0x1: /* and */
3020 3021 3022 3023 3024 3025 3026
                        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) {
3027 3028 3029
                            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;
3030
                        }
3031
                        break;
3032
                    case 0x2: /* or */
3033 3034 3035 3036 3037 3038
                        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);
                        }
3039
                        if (xop & 0x10) {
3040 3041 3042
                            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;
3043
                        }
B
blueswir1 已提交
3044
                        break;
3045
                    case 0x3: /* xor */
3046 3047 3048 3049 3050 3051
                        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);
                        }
3052
                        if (xop & 0x10) {
3053 3054 3055
                            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;
3056
                        }
3057
                        break;
3058
                    case 0x4: /* sub */
3059 3060 3061
                        if (IS_IMM) {
                            simm = GET_FIELDs(insn, 19, 31);
                            if (xop & 0x10) {
B
Blue Swirl 已提交
3062
                                gen_op_subi_cc(cpu_dst, cpu_src1, simm, dc);
3063 3064 3065 3066 3067 3068
                            } 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 已提交
3069 3070
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
                                dc->cc_op = CC_OP_SUB;
3071 3072 3073 3074
                            } else {
                                tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
                            }
                        }
3075
                        break;
3076
                    case 0x5: /* andn */
3077 3078 3079 3080 3081 3082
                        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);
                        }
3083
                        if (xop & 0x10) {
3084 3085 3086
                            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;
3087
                        }
3088
                        break;
3089
                    case 0x6: /* orn */
3090 3091 3092 3093 3094 3095
                        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);
                        }
3096
                        if (xop & 0x10) {
3097 3098 3099
                            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;
3100
                        }
3101
                        break;
3102
                    case 0x7: /* xorn */
3103 3104 3105 3106 3107 3108 3109
                        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);
                        }
3110
                        if (xop & 0x10) {
3111 3112 3113
                            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;
3114
                        }
3115
                        break;
3116
                    case 0x8: /* addx, V9 addc */
3117 3118
                        gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
                                        (xop & 0x10));
3119
                        break;
P
pbrook 已提交
3120
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3121
                    case 0x9: /* V9 mulx */
3122 3123 3124 3125 3126 3127
                        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 已提交
3128 3129
                        break;
#endif
3130
                    case 0xa: /* umul */
B
blueswir1 已提交
3131
                        CHECK_IU_FEATURE(dc, MUL);
3132
                        gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
3133
                        if (xop & 0x10) {
3134 3135 3136
                            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;
3137
                        }
3138
                        break;
3139
                    case 0xb: /* smul */
B
blueswir1 已提交
3140
                        CHECK_IU_FEATURE(dc, MUL);
3141
                        gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
3142
                        if (xop & 0x10) {
3143 3144 3145
                            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;
3146
                        }
3147
                        break;
3148
                    case 0xc: /* subx, V9 subc */
3149 3150
                        gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
                                        (xop & 0x10));
3151
                        break;
P
pbrook 已提交
3152
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3153
                    case 0xd: /* V9 udivx */
3154 3155 3156 3157
                        tcg_gen_mov_tl(cpu_cc_src, cpu_src1);
                        tcg_gen_mov_tl(cpu_cc_src2, cpu_src2);
                        gen_trap_ifdivzero_tl(cpu_cc_src2);
                        tcg_gen_divu_i64(cpu_dst, cpu_cc_src, cpu_cc_src2);
P
pbrook 已提交
3158 3159
                        break;
#endif
3160
                    case 0xe: /* udiv */
B
blueswir1 已提交
3161
                        CHECK_IU_FEATURE(dc, DIV);
P
pbrook 已提交
3162
                        gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
3163
                        if (xop & 0x10) {
B
Blue Swirl 已提交
3164 3165 3166
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
                            dc->cc_op = CC_OP_DIV;
3167
                        }
3168
                        break;
3169
                    case 0xf: /* sdiv */
B
blueswir1 已提交
3170
                        CHECK_IU_FEATURE(dc, DIV);
P
pbrook 已提交
3171
                        gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
3172
                        if (xop & 0x10) {
B
Blue Swirl 已提交
3173 3174 3175
                            tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
                            dc->cc_op = CC_OP_DIV;
3176
                        }
3177 3178 3179 3180
                        break;
                    default:
                        goto illegal_insn;
                    }
3181
                    gen_movl_TN_reg(rd, cpu_dst);
3182
                } else {
3183 3184
                    cpu_src1 = get_src1(insn, cpu_src1);
                    cpu_src2 = get_src2(insn, cpu_src2);
3185
                    switch (xop) {
B
blueswir1 已提交
3186
                    case 0x20: /* taddcc */
3187 3188
                        gen_op_tadd_cc(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3189 3190
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
                        dc->cc_op = CC_OP_TADD;
B
blueswir1 已提交
3191 3192
                        break;
                    case 0x21: /* tsubcc */
3193 3194
                        gen_op_tsub_cc(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3195 3196
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
                        dc->cc_op = CC_OP_TSUB;
B
blueswir1 已提交
3197 3198
                        break;
                    case 0x22: /* taddcctv */
3199 3200 3201
                        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 已提交
3202 3203
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV);
                        dc->cc_op = CC_OP_TADDTV;
B
blueswir1 已提交
3204 3205
                        break;
                    case 0x23: /* tsubcctv */
3206 3207 3208
                        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 已提交
3209 3210
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV);
                        dc->cc_op = CC_OP_TSUBTV;
B
blueswir1 已提交
3211
                        break;
3212
                    case 0x24: /* mulscc */
3213
                        gen_helper_compute_psr();
3214 3215
                        gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
Blue Swirl 已提交
3216 3217
                        tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
                        dc->cc_op = CC_OP_ADD;
3218
                        break;
B
bellard 已提交
3219
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3220
                    case 0x25:  /* sll */
3221
                        if (IS_IMM) { /* immediate */
B
Blue Swirl 已提交
3222 3223
                            simm = GET_FIELDs(insn, 20, 31);
                            tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
3224 3225 3226 3227
                        } else { /* register */
                            tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
                            tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3228
                        gen_movl_TN_reg(rd, cpu_dst);
3229
                        break;
B
bellard 已提交
3230
                    case 0x26:  /* srl */
3231
                        if (IS_IMM) { /* immediate */
B
Blue Swirl 已提交
3232 3233
                            simm = GET_FIELDs(insn, 20, 31);
                            tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
3234 3235 3236 3237
                        } else { /* register */
                            tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
                            tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3238
                        gen_movl_TN_reg(rd, cpu_dst);
3239
                        break;
B
bellard 已提交
3240
                    case 0x27:  /* sra */
3241
                        if (IS_IMM) { /* immediate */
B
Blue Swirl 已提交
3242 3243
                            simm = GET_FIELDs(insn, 20, 31);
                            tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
3244 3245 3246 3247
                        } else { /* register */
                            tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
                            tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
                        }
3248
                        gen_movl_TN_reg(rd, cpu_dst);
3249
                        break;
B
bellard 已提交
3250
#endif
3251 3252 3253
                    case 0x30:
                        {
                            switch(rd) {
B
bellard 已提交
3254
                            case 0: /* wry */
3255 3256
                                tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
                                tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
3257
                                break;
3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268
#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 已提交
3269
                            case 0x2: /* V9 wrccr */
3270
                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
P
pbrook 已提交
3271
                                gen_helper_wrccr(cpu_dst);
3272 3273
                                tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
                                dc->cc_op = CC_OP_FLAGS;
B
blueswir1 已提交
3274 3275
                                break;
                            case 0x3: /* V9 wrasi */
3276
                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
I
Igor V. Kovalenko 已提交
3277
                                tcg_gen_andi_tl(cpu_dst, cpu_dst, 0xff);
3278
                                tcg_gen_trunc_tl_i32(cpu_asi, cpu_dst);
B
blueswir1 已提交
3279 3280
                                break;
                            case 0x6: /* V9 wrfprs */
3281
                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
3282
                                tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst);
3283
                                save_state(dc, cpu_cond);
3284
                                gen_op_next_insn();
B
bellard 已提交
3285
                                tcg_gen_exit_tb(0);
3286
                                dc->is_br = 1;
B
blueswir1 已提交
3287 3288
                                break;
                            case 0xf: /* V9 sir, nop if user */
B
bellard 已提交
3289
#if !defined(CONFIG_USER_ONLY)
3290
                                if (supervisor(dc)) {
B
blueswir1 已提交
3291
                                    ; // XXX
3292
                                }
B
bellard 已提交
3293
#endif
B
blueswir1 已提交
3294 3295
                                break;
                            case 0x13: /* Graphics Status */
3296
                                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
3297
                                    goto jmp_insn;
3298
                                tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
B
blueswir1 已提交
3299
                                break;
3300 3301 3302 3303
                            case 0x14: /* Softint set */
                                if (!supervisor(dc))
                                    goto illegal_insn;
                                tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
P
pbrook 已提交
3304
                                gen_helper_set_softint(cpu_tmp64);
3305 3306 3307 3308 3309
                                break;
                            case 0x15: /* Softint clear */
                                if (!supervisor(dc))
                                    goto illegal_insn;
                                tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
P
pbrook 已提交
3310
                                gen_helper_clear_softint(cpu_tmp64);
3311 3312 3313 3314 3315
                                break;
                            case 0x16: /* Softint write */
                                if (!supervisor(dc))
                                    goto illegal_insn;
                                tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
P
pbrook 已提交
3316
                                gen_helper_write_softint(cpu_tmp64);
3317
                                break;
B
blueswir1 已提交
3318
                            case 0x17: /* Tick compare */
B
bellard 已提交
3319
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3320 3321
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
3322
#endif
B
blueswir1 已提交
3323
                                {
P
pbrook 已提交
3324
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3325

3326
                                    tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
3327
                                                   cpu_src2);
P
pbrook 已提交
3328
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3329 3330
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, tick));
P
pbrook 已提交
3331 3332 3333
                                    gen_helper_tick_set_limit(r_tickptr,
                                                              cpu_tick_cmpr);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3334
                                }
B
blueswir1 已提交
3335 3336
                                break;
                            case 0x18: /* System tick */
B
bellard 已提交
3337
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3338 3339
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
3340
#endif
B
blueswir1 已提交
3341
                                {
P
pbrook 已提交
3342
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3343

3344 3345
                                    tcg_gen_xor_tl(cpu_dst, cpu_src1,
                                                   cpu_src2);
P
pbrook 已提交
3346
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3347 3348
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, stick));
P
pbrook 已提交
3349 3350 3351
                                    gen_helper_tick_set_count(r_tickptr,
                                                              cpu_dst);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3352
                                }
B
blueswir1 已提交
3353 3354
                                break;
                            case 0x19: /* System tick compare */
B
bellard 已提交
3355
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3356 3357
                                if (!supervisor(dc))
                                    goto illegal_insn;
B
bellard 已提交
3358
#endif
B
blueswir1 已提交
3359
                                {
P
pbrook 已提交
3360
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3361

3362
                                    tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
3363
                                                   cpu_src2);
P
pbrook 已提交
3364
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3365 3366
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, stick));
P
pbrook 已提交
3367 3368 3369
                                    gen_helper_tick_set_limit(r_tickptr,
                                                              cpu_stick_cmpr);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3370
                                }
B
blueswir1 已提交
3371
                                break;
B
bellard 已提交
3372

B
blueswir1 已提交
3373
                            case 0x10: /* Performance Control */
B
blueswir1 已提交
3374 3375
                            case 0x11: /* Performance Instrumentation
                                          Counter */
B
blueswir1 已提交
3376
                            case 0x12: /* Dispatch Control */
B
bellard 已提交
3377
#endif
B
bellard 已提交
3378
                            default:
3379 3380 3381 3382
                                goto illegal_insn;
                            }
                        }
                        break;
3383
#if !defined(CONFIG_USER_ONLY)
3384
                    case 0x31: /* wrpsr, V9 saved, restored */
3385
                        {
B
blueswir1 已提交
3386 3387
                            if (!supervisor(dc))
                                goto priv_insn;
B
bellard 已提交
3388
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3389 3390
                            switch (rd) {
                            case 0:
P
pbrook 已提交
3391
                                gen_helper_saved();
B
blueswir1 已提交
3392 3393
                                break;
                            case 1:
P
pbrook 已提交
3394
                                gen_helper_restored();
B
blueswir1 已提交
3395
                                break;
B
blueswir1 已提交
3396 3397 3398 3399 3400
                            case 2: /* UA2005 allclean */
                            case 3: /* UA2005 otherw */
                            case 4: /* UA2005 normalw */
                            case 5: /* UA2005 invalw */
                                // XXX
B
blueswir1 已提交
3401
                            default:
B
bellard 已提交
3402 3403 3404
                                goto illegal_insn;
                            }
#else
3405
                            tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
P
pbrook 已提交
3406
                            gen_helper_wrpsr(cpu_dst);
3407 3408
                            tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
                            dc->cc_op = CC_OP_FLAGS;
3409
                            save_state(dc, cpu_cond);
B
bellard 已提交
3410
                            gen_op_next_insn();
B
bellard 已提交
3411
                            tcg_gen_exit_tb(0);
B
blueswir1 已提交
3412
                            dc->is_br = 1;
B
bellard 已提交
3413
#endif
3414 3415
                        }
                        break;
3416
                    case 0x32: /* wrwim, V9 wrpr */
3417
                        {
B
blueswir1 已提交
3418 3419
                            if (!supervisor(dc))
                                goto priv_insn;
3420
                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
B
bellard 已提交
3421
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3422 3423
                            switch (rd) {
                            case 0: // tpc
3424
                                {
P
pbrook 已提交
3425
                                    TCGv_ptr r_tsptr;
3426

P
pbrook 已提交
3427
                                    r_tsptr = tcg_temp_new_ptr();
3428
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3429
                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
3430
                                                  offsetof(trap_state, tpc));
P
pbrook 已提交
3431
                                    tcg_temp_free_ptr(r_tsptr);
3432
                                }
B
blueswir1 已提交
3433 3434
                                break;
                            case 1: // tnpc
3435
                                {
P
pbrook 已提交
3436
                                    TCGv_ptr r_tsptr;
3437

P
pbrook 已提交
3438
                                    r_tsptr = tcg_temp_new_ptr();
3439
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3440
                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
3441
                                                  offsetof(trap_state, tnpc));
P
pbrook 已提交
3442
                                    tcg_temp_free_ptr(r_tsptr);
3443
                                }
B
blueswir1 已提交
3444 3445
                                break;
                            case 2: // tstate
3446
                                {
P
pbrook 已提交
3447
                                    TCGv_ptr r_tsptr;
3448

P
pbrook 已提交
3449
                                    r_tsptr = tcg_temp_new_ptr();
3450
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3451
                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
B
blueswir1 已提交
3452 3453
                                                  offsetof(trap_state,
                                                           tstate));
P
pbrook 已提交
3454
                                    tcg_temp_free_ptr(r_tsptr);
3455
                                }
B
blueswir1 已提交
3456 3457
                                break;
                            case 3: // tt
3458
                                {
P
pbrook 已提交
3459
                                    TCGv_ptr r_tsptr;
3460

P
pbrook 已提交
3461
                                    r_tsptr = tcg_temp_new_ptr();
3462
                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
B
blueswir1 已提交
3463 3464
                                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                    tcg_gen_st_i32(cpu_tmp32, r_tsptr,
3465
                                                   offsetof(trap_state, tt));
P
pbrook 已提交
3466
                                    tcg_temp_free_ptr(r_tsptr);
3467
                                }
B
blueswir1 已提交
3468 3469
                                break;
                            case 4: // tick
B
blueswir1 已提交
3470
                                {
P
pbrook 已提交
3471
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3472

P
pbrook 已提交
3473
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3474 3475
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, tick));
P
pbrook 已提交
3476 3477 3478
                                    gen_helper_tick_set_count(r_tickptr,
                                                              cpu_tmp0);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3479
                                }
B
blueswir1 已提交
3480 3481
                                break;
                            case 5: // tba
3482
                                tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
B
blueswir1 已提交
3483 3484
                                break;
                            case 6: // pstate
3485
                                save_state(dc, cpu_cond);
P
pbrook 已提交
3486
                                gen_helper_wrpstate(cpu_tmp0);
3487
                                dc->npc = DYNAMIC_PC;
B
blueswir1 已提交
3488 3489
                                break;
                            case 7: // tl
3490
                                save_state(dc, cpu_cond);
3491
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3492 3493
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState, tl));
3494
                                dc->npc = DYNAMIC_PC;
B
blueswir1 已提交
3495 3496
                                break;
                            case 8: // pil
3497
                                gen_helper_wrpil(cpu_tmp0);
B
blueswir1 已提交
3498 3499
                                break;
                            case 9: // cwp
P
pbrook 已提交
3500
                                gen_helper_wrcwp(cpu_tmp0);
B
blueswir1 已提交
3501 3502
                                break;
                            case 10: // cansave
3503
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3504 3505 3506
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        cansave));
B
blueswir1 已提交
3507 3508
                                break;
                            case 11: // canrestore
3509
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3510 3511 3512
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        canrestore));
B
blueswir1 已提交
3513 3514
                                break;
                            case 12: // cleanwin
3515
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3516 3517 3518
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        cleanwin));
B
blueswir1 已提交
3519 3520
                                break;
                            case 13: // otherwin
3521
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3522 3523 3524
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        otherwin));
B
blueswir1 已提交
3525 3526
                                break;
                            case 14: // wstate
3527
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3528 3529 3530
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState,
                                                        wstate));
B
blueswir1 已提交
3531
                                break;
B
blueswir1 已提交
3532
                            case 16: // UA2005 gl
3533
                                CHECK_IU_FEATURE(dc, GL);
3534
                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3535 3536
                                tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                               offsetof(CPUSPARCState, gl));
B
blueswir1 已提交
3537 3538
                                break;
                            case 26: // UA2005 strand status
3539
                                CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
3540 3541
                                if (!hypervisor(dc))
                                    goto priv_insn;
B
blueswir1 已提交
3542
                                tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
B
blueswir1 已提交
3543
                                break;
B
blueswir1 已提交
3544 3545 3546
                            default:
                                goto illegal_insn;
                            }
B
bellard 已提交
3547
#else
3548
                            tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
B
blueswir1 已提交
3549 3550 3551
                            if (dc->def->nwindows != 32)
                                tcg_gen_andi_tl(cpu_tmp32, cpu_tmp32,
                                                (1 << dc->def->nwindows) - 1);
3552
                            tcg_gen_mov_i32(cpu_wim, cpu_tmp32);
B
bellard 已提交
3553
#endif
3554 3555
                        }
                        break;
B
blueswir1 已提交
3556
                    case 0x33: /* wrtbr, UA2005 wrhpr */
3557
                        {
B
blueswir1 已提交
3558
#ifndef TARGET_SPARC64
B
blueswir1 已提交
3559 3560
                            if (!supervisor(dc))
                                goto priv_insn;
3561
                            tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
B
blueswir1 已提交
3562
#else
3563
                            CHECK_IU_FEATURE(dc, HYPV);
B
blueswir1 已提交
3564 3565
                            if (!hypervisor(dc))
                                goto priv_insn;
3566
                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
B
blueswir1 已提交
3567 3568 3569
                            switch (rd) {
                            case 0: // hpstate
                                // XXX gen_op_wrhpstate();
3570
                                save_state(dc, cpu_cond);
B
blueswir1 已提交
3571
                                gen_op_next_insn();
B
bellard 已提交
3572
                                tcg_gen_exit_tb(0);
B
blueswir1 已提交
3573 3574 3575 3576 3577 3578
                                dc->is_br = 1;
                                break;
                            case 1: // htstate
                                // XXX gen_op_wrhtstate();
                                break;
                            case 3: // hintp
3579
                                tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
B
blueswir1 已提交
3580 3581
                                break;
                            case 5: // htba
3582
                                tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
B
blueswir1 已提交
3583 3584
                                break;
                            case 31: // hstick_cmpr
B
blueswir1 已提交
3585
                                {
P
pbrook 已提交
3586
                                    TCGv_ptr r_tickptr;
B
blueswir1 已提交
3587

3588
                                    tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
P
pbrook 已提交
3589
                                    r_tickptr = tcg_temp_new_ptr();
B
blueswir1 已提交
3590 3591
                                    tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                   offsetof(CPUState, hstick));
P
pbrook 已提交
3592 3593 3594
                                    gen_helper_tick_set_limit(r_tickptr,
                                                              cpu_hstick_cmpr);
                                    tcg_temp_free_ptr(r_tickptr);
B
blueswir1 已提交
3595
                                }
B
blueswir1 已提交
3596 3597 3598 3599 3600 3601
                                break;
                            case 6: // hver readonly
                            default:
                                goto illegal_insn;
                            }
#endif
3602 3603 3604
                        }
                        break;
#endif
B
bellard 已提交
3605
#ifdef TARGET_SPARC64
B
blueswir1 已提交
3606 3607 3608 3609
                    case 0x2c: /* V9 movcc */
                        {
                            int cc = GET_FIELD_SP(insn, 11, 12);
                            int cond = GET_FIELD_SP(insn, 14, 17);
B
blueswir1 已提交
3610
                            TCGv r_cond;
3611 3612
                            int l1;

P
pbrook 已提交
3613
                            r_cond = tcg_temp_new();
B
blueswir1 已提交
3614 3615
                            if (insn & (1 << 18)) {
                                if (cc == 0)
3616
                                    gen_cond(r_cond, 0, cond, dc);
B
blueswir1 已提交
3617
                                else if (cc == 2)
3618
                                    gen_cond(r_cond, 1, cond, dc);
B
blueswir1 已提交
3619 3620 3621
                                else
                                    goto illegal_insn;
                            } else {
B
blueswir1 已提交
3622
                                gen_fcond(r_cond, cc, cond);
B
blueswir1 已提交
3623
                            }
3624 3625 3626

                            l1 = gen_new_label();

P
pbrook 已提交
3627
                            tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
3628
                            if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
3629 3630
                                TCGv r_const;

B
Blue Swirl 已提交
3631 3632
                                simm = GET_FIELD_SPs(insn, 0, 10);
                                r_const = tcg_const_tl(simm);
B
blueswir1 已提交
3633 3634
                                gen_movl_TN_reg(rd, r_const);
                                tcg_temp_free(r_const);
3635 3636
                            } else {
                                rs2 = GET_FIELD_SP(insn, 0, 4);
B
blueswir1 已提交
3637 3638
                                gen_movl_reg_TN(rs2, cpu_tmp0);
                                gen_movl_TN_reg(rd, cpu_tmp0);
3639 3640
                            }
                            gen_set_label(l1);
B
blueswir1 已提交
3641
                            tcg_temp_free(r_cond);
B
blueswir1 已提交
3642 3643 3644
                            break;
                        }
                    case 0x2d: /* V9 sdivx */
3645 3646
                        gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2);
                        gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3647 3648 3649
                        break;
                    case 0x2e: /* V9 popc */
                        {
B
blueswir1 已提交
3650
                            cpu_src2 = get_src2(insn, cpu_src2);
P
pbrook 已提交
3651
                            gen_helper_popc(cpu_dst, cpu_src2);
3652
                            gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3653 3654 3655 3656
                        }
                    case 0x2f: /* V9 movr */
                        {
                            int cond = GET_FIELD_SP(insn, 10, 12);
3657 3658
                            int l1;

3659
                            cpu_src1 = get_src1(insn, cpu_src1);
3660 3661 3662

                            l1 = gen_new_label();

P
pbrook 已提交
3663 3664
                            tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond],
                                              cpu_src1, 0, l1);
B
blueswir1 已提交
3665
                            if (IS_IMM) {       /* immediate */
B
blueswir1 已提交
3666 3667
                                TCGv r_const;

B
Blue Swirl 已提交
3668 3669
                                simm = GET_FIELD_SPs(insn, 0, 9);
                                r_const = tcg_const_tl(simm);
B
blueswir1 已提交
3670 3671
                                gen_movl_TN_reg(rd, r_const);
                                tcg_temp_free(r_const);
3672
                            } else {
B
blueswir1 已提交
3673
                                rs2 = GET_FIELD_SP(insn, 0, 4);
B
blueswir1 已提交
3674 3675
                                gen_movl_reg_TN(rs2, cpu_tmp0);
                                gen_movl_TN_reg(rd, cpu_tmp0);
B
blueswir1 已提交
3676
                            }
3677
                            gen_set_label(l1);
B
blueswir1 已提交
3678 3679 3680 3681 3682 3683 3684
                            break;
                        }
#endif
                    default:
                        goto illegal_insn;
                    }
                }
3685 3686 3687 3688 3689
            } 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);
3690
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
blueswir1 已提交
3691
                    goto jmp_insn;
3692 3693

                switch (opf) {
B
blueswir1 已提交
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708
                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 已提交
3709
                    CHECK_FPU_FEATURE(dc, VIS1);
3710
                    cpu_src1 = get_src1(insn, cpu_src1);
3711
                    gen_movl_reg_TN(rs2, cpu_src2);
P
pbrook 已提交
3712
                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
3713
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3714 3715
                    break;
                case 0x012: /* VIS I array16 */
B
blueswir1 已提交
3716
                    CHECK_FPU_FEATURE(dc, VIS1);
3717
                    cpu_src1 = get_src1(insn, cpu_src1);
3718
                    gen_movl_reg_TN(rs2, cpu_src2);
P
pbrook 已提交
3719
                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
3720 3721
                    tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3722 3723
                    break;
                case 0x014: /* VIS I array32 */
B
blueswir1 已提交
3724
                    CHECK_FPU_FEATURE(dc, VIS1);
3725
                    cpu_src1 = get_src1(insn, cpu_src1);
3726
                    gen_movl_reg_TN(rs2, cpu_src2);
P
pbrook 已提交
3727
                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
3728 3729
                    tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
3730
                    break;
3731
                case 0x018: /* VIS I alignaddr */
B
blueswir1 已提交
3732
                    CHECK_FPU_FEATURE(dc, VIS1);
3733
                    cpu_src1 = get_src1(insn, cpu_src1);
3734
                    gen_movl_reg_TN(rs2, cpu_src2);
P
pbrook 已提交
3735
                    gen_helper_alignaddr(cpu_dst, cpu_src1, cpu_src2);
3736
                    gen_movl_TN_reg(rd, cpu_dst);
3737
                    break;
B
blueswir1 已提交
3738
                case 0x019: /* VIS II bmask */
3739 3740
                case 0x01a: /* VIS I alignaddrl */
                    // XXX
B
blueswir1 已提交
3741 3742
                    goto illegal_insn;
                case 0x020: /* VIS I fcmple16 */
B
blueswir1 已提交
3743
                    CHECK_FPU_FEATURE(dc, VIS1);
3744 3745
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3746
                    gen_helper_fcmple16();
3747
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3748 3749
                    break;
                case 0x022: /* VIS I fcmpne16 */
B
blueswir1 已提交
3750
                    CHECK_FPU_FEATURE(dc, VIS1);
3751 3752
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3753
                    gen_helper_fcmpne16();
3754
                    gen_op_store_DT0_fpr(DFPREG(rd));
3755
                    break;
B
blueswir1 已提交
3756
                case 0x024: /* VIS I fcmple32 */
B
blueswir1 已提交
3757
                    CHECK_FPU_FEATURE(dc, VIS1);
3758 3759
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3760
                    gen_helper_fcmple32();
3761
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3762 3763
                    break;
                case 0x026: /* VIS I fcmpne32 */
B
blueswir1 已提交
3764
                    CHECK_FPU_FEATURE(dc, VIS1);
3765 3766
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3767
                    gen_helper_fcmpne32();
3768
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3769 3770
                    break;
                case 0x028: /* VIS I fcmpgt16 */
B
blueswir1 已提交
3771
                    CHECK_FPU_FEATURE(dc, VIS1);
3772 3773
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3774
                    gen_helper_fcmpgt16();
3775
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3776 3777
                    break;
                case 0x02a: /* VIS I fcmpeq16 */
B
blueswir1 已提交
3778
                    CHECK_FPU_FEATURE(dc, VIS1);
3779 3780
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3781
                    gen_helper_fcmpeq16();
3782
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3783 3784
                    break;
                case 0x02c: /* VIS I fcmpgt32 */
B
blueswir1 已提交
3785
                    CHECK_FPU_FEATURE(dc, VIS1);
3786 3787
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3788
                    gen_helper_fcmpgt32();
3789
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3790 3791
                    break;
                case 0x02e: /* VIS I fcmpeq32 */
B
blueswir1 已提交
3792
                    CHECK_FPU_FEATURE(dc, VIS1);
3793 3794
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3795
                    gen_helper_fcmpeq32();
3796
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3797 3798
                    break;
                case 0x031: /* VIS I fmul8x16 */
B
blueswir1 已提交
3799
                    CHECK_FPU_FEATURE(dc, VIS1);
3800 3801
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3802
                    gen_helper_fmul8x16();
3803
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3804 3805
                    break;
                case 0x033: /* VIS I fmul8x16au */
B
blueswir1 已提交
3806
                    CHECK_FPU_FEATURE(dc, VIS1);
3807 3808
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3809
                    gen_helper_fmul8x16au();
3810
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3811 3812
                    break;
                case 0x035: /* VIS I fmul8x16al */
B
blueswir1 已提交
3813
                    CHECK_FPU_FEATURE(dc, VIS1);
3814 3815
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3816
                    gen_helper_fmul8x16al();
3817
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3818 3819
                    break;
                case 0x036: /* VIS I fmul8sux16 */
B
blueswir1 已提交
3820
                    CHECK_FPU_FEATURE(dc, VIS1);
3821 3822
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3823
                    gen_helper_fmul8sux16();
3824
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3825 3826
                    break;
                case 0x037: /* VIS I fmul8ulx16 */
B
blueswir1 已提交
3827
                    CHECK_FPU_FEATURE(dc, VIS1);
3828 3829
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3830
                    gen_helper_fmul8ulx16();
3831
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3832 3833
                    break;
                case 0x038: /* VIS I fmuld8sux16 */
B
blueswir1 已提交
3834
                    CHECK_FPU_FEATURE(dc, VIS1);
3835 3836
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3837
                    gen_helper_fmuld8sux16();
3838
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3839 3840
                    break;
                case 0x039: /* VIS I fmuld8ulx16 */
B
blueswir1 已提交
3841
                    CHECK_FPU_FEATURE(dc, VIS1);
3842 3843
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3844
                    gen_helper_fmuld8ulx16();
3845
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3846 3847 3848 3849 3850 3851 3852
                    break;
                case 0x03a: /* VIS I fpack32 */
                case 0x03b: /* VIS I fpack16 */
                case 0x03d: /* VIS I fpackfix */
                case 0x03e: /* VIS I pdist */
                    // XXX
                    goto illegal_insn;
3853
                case 0x048: /* VIS I faligndata */
B
blueswir1 已提交
3854
                    CHECK_FPU_FEATURE(dc, VIS1);
3855 3856
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3857
                    gen_helper_faligndata();
3858
                    gen_op_store_DT0_fpr(DFPREG(rd));
3859
                    break;
B
blueswir1 已提交
3860
                case 0x04b: /* VIS I fpmerge */
B
blueswir1 已提交
3861
                    CHECK_FPU_FEATURE(dc, VIS1);
3862 3863
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3864
                    gen_helper_fpmerge();
3865
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3866 3867 3868 3869 3870
                    break;
                case 0x04c: /* VIS II bshuffle */
                    // XXX
                    goto illegal_insn;
                case 0x04d: /* VIS I fexpand */
B
blueswir1 已提交
3871
                    CHECK_FPU_FEATURE(dc, VIS1);
3872 3873
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3874
                    gen_helper_fexpand();
3875
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3876 3877
                    break;
                case 0x050: /* VIS I fpadd16 */
B
blueswir1 已提交
3878
                    CHECK_FPU_FEATURE(dc, VIS1);
3879 3880
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3881
                    gen_helper_fpadd16();
3882
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3883 3884
                    break;
                case 0x051: /* VIS I fpadd16s */
B
blueswir1 已提交
3885
                    CHECK_FPU_FEATURE(dc, VIS1);
P
pbrook 已提交
3886 3887
                    gen_helper_fpadd16s(cpu_fpr[rd],
                                        cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
3888 3889
                    break;
                case 0x052: /* VIS I fpadd32 */
B
blueswir1 已提交
3890
                    CHECK_FPU_FEATURE(dc, VIS1);
3891 3892
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3893
                    gen_helper_fpadd32();
3894
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3895 3896
                    break;
                case 0x053: /* VIS I fpadd32s */
B
blueswir1 已提交
3897
                    CHECK_FPU_FEATURE(dc, VIS1);
P
pbrook 已提交
3898 3899
                    gen_helper_fpadd32s(cpu_fpr[rd],
                                        cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
3900 3901
                    break;
                case 0x054: /* VIS I fpsub16 */
B
blueswir1 已提交
3902
                    CHECK_FPU_FEATURE(dc, VIS1);
3903 3904
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3905
                    gen_helper_fpsub16();
3906
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3907 3908
                    break;
                case 0x055: /* VIS I fpsub16s */
B
blueswir1 已提交
3909
                    CHECK_FPU_FEATURE(dc, VIS1);
P
pbrook 已提交
3910 3911
                    gen_helper_fpsub16s(cpu_fpr[rd],
                                        cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
3912 3913
                    break;
                case 0x056: /* VIS I fpsub32 */
B
blueswir1 已提交
3914
                    CHECK_FPU_FEATURE(dc, VIS1);
3915 3916
                    gen_op_load_fpr_DT0(DFPREG(rs1));
                    gen_op_load_fpr_DT1(DFPREG(rs2));
P
pbrook 已提交
3917
                    gen_helper_fpsub32();
3918
                    gen_op_store_DT0_fpr(DFPREG(rd));
B
blueswir1 已提交
3919 3920
                    break;
                case 0x057: /* VIS I fpsub32s */
B
blueswir1 已提交
3921
                    CHECK_FPU_FEATURE(dc, VIS1);
P
pbrook 已提交
3922 3923
                    gen_helper_fpsub32s(cpu_fpr[rd],
                                        cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
3924
                    break;
3925
                case 0x060: /* VIS I fzero */
B
blueswir1 已提交
3926
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3927 3928
                    tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], 0);
                    tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], 0);
3929 3930
                    break;
                case 0x061: /* VIS I fzeros */
B
blueswir1 已提交
3931
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3932
                    tcg_gen_movi_i32(cpu_fpr[rd], 0);
3933
                    break;
B
blueswir1 已提交
3934
                case 0x062: /* VIS I fnor */
B
blueswir1 已提交
3935
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3936 3937 3938 3939
                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)],
                                    cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
3940 3941
                    break;
                case 0x063: /* VIS I fnors */
B
blueswir1 已提交
3942
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3943
                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
3944 3945
                    break;
                case 0x064: /* VIS I fandnot2 */
B
blueswir1 已提交
3946
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3947 3948 3949 3950 3951
                    tcg_gen_andc_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                     cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
3952 3953
                    break;
                case 0x065: /* VIS I fandnot2s */
B
blueswir1 已提交
3954
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3955
                    tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
3956 3957
                    break;
                case 0x066: /* VIS I fnot2 */
B
blueswir1 已提交
3958
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3959 3960 3961
                    tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
3962 3963
                    break;
                case 0x067: /* VIS I fnot2s */
B
blueswir1 已提交
3964
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3965
                    tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs2]);
B
blueswir1 已提交
3966 3967
                    break;
                case 0x068: /* VIS I fandnot1 */
B
blueswir1 已提交
3968
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3969 3970 3971 3972 3973
                    tcg_gen_andc_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)],
                                     cpu_fpr[DFPREG(rs1)]);
                    tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
B
blueswir1 已提交
3974 3975
                    break;
                case 0x069: /* VIS I fandnot1s */
B
blueswir1 已提交
3976
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3977
                    tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
B
blueswir1 已提交
3978 3979
                    break;
                case 0x06a: /* VIS I fnot1 */
B
blueswir1 已提交
3980
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3981 3982 3983
                    tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                    tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1]);
B
blueswir1 已提交
3984 3985
                    break;
                case 0x06b: /* VIS I fnot1s */
B
blueswir1 已提交
3986
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3987
                    tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs1]);
B
blueswir1 已提交
3988 3989
                    break;
                case 0x06c: /* VIS I fxor */
B
blueswir1 已提交
3990
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3991 3992 3993 3994 3995
                    tcg_gen_xor_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                    cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
3996 3997
                    break;
                case 0x06d: /* VIS I fxors */
B
blueswir1 已提交
3998
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
3999
                    tcg_gen_xor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
4000 4001
                    break;
                case 0x06e: /* VIS I fnand */
B
blueswir1 已提交
4002
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4003 4004 4005 4006
                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)],
                                     cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
4007 4008
                    break;
                case 0x06f: /* VIS I fnands */
B
blueswir1 已提交
4009
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4010
                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
4011 4012
                    break;
                case 0x070: /* VIS I fand */
B
blueswir1 已提交
4013
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4014 4015 4016 4017 4018
                    tcg_gen_and_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                    cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_and_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
4019 4020
                    break;
                case 0x071: /* VIS I fands */
B
blueswir1 已提交
4021
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4022
                    tcg_gen_and_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
4023 4024
                    break;
                case 0x072: /* VIS I fxnor */
B
blueswir1 已提交
4025
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4026 4027 4028 4029 4030 4031
                    tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[DFPREG(rs2)], -1);
                    tcg_gen_xor_i32(cpu_fpr[DFPREG(rd)], cpu_tmp32,
                                    cpu_fpr[DFPREG(rs1)]);
                    tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[DFPREG(rs2) + 1], -1);
                    tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1], cpu_tmp32,
                                    cpu_fpr[DFPREG(rs1) + 1]);
B
blueswir1 已提交
4032 4033
                    break;
                case 0x073: /* VIS I fxnors */
B
blueswir1 已提交
4034
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4035 4036
                    tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[rs2], -1);
                    tcg_gen_xor_i32(cpu_fpr[rd], cpu_tmp32, cpu_fpr[rs1]);
B
blueswir1 已提交
4037
                    break;
4038
                case 0x074: /* VIS I fsrc1 */
B
blueswir1 已提交
4039
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4040 4041 4042
                    tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                    tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1]);
4043 4044
                    break;
                case 0x075: /* VIS I fsrc1s */
B
blueswir1 已提交
4045
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4046
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs1]);
4047
                    break;
B
blueswir1 已提交
4048
                case 0x076: /* VIS I fornot2 */
B
blueswir1 已提交
4049
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4050 4051 4052 4053 4054
                    tcg_gen_orc_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                    cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
4055 4056
                    break;
                case 0x077: /* VIS I fornot2s */
B
blueswir1 已提交
4057
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4058
                    tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
4059
                    break;
4060
                case 0x078: /* VIS I fsrc2 */
B
blueswir1 已提交
4061
                    CHECK_FPU_FEATURE(dc, VIS1);
4062 4063
                    gen_op_load_fpr_DT0(DFPREG(rs2));
                    gen_op_store_DT0_fpr(DFPREG(rd));
4064 4065
                    break;
                case 0x079: /* VIS I fsrc2s */
B
blueswir1 已提交
4066
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4067
                    tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
4068
                    break;
B
blueswir1 已提交
4069
                case 0x07a: /* VIS I fornot1 */
B
blueswir1 已提交
4070
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4071 4072 4073 4074 4075
                    tcg_gen_orc_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)],
                                    cpu_fpr[DFPREG(rs1)]);
                    tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1]);
B
blueswir1 已提交
4076 4077
                    break;
                case 0x07b: /* VIS I fornot1s */
B
blueswir1 已提交
4078
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4079
                    tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
B
blueswir1 已提交
4080 4081
                    break;
                case 0x07c: /* VIS I for */
B
blueswir1 已提交
4082
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4083 4084 4085 4086 4087
                    tcg_gen_or_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                   cpu_fpr[DFPREG(rs2)]);
                    tcg_gen_or_i32(cpu_fpr[DFPREG(rd) + 1],
                                   cpu_fpr[DFPREG(rs1) + 1],
                                   cpu_fpr[DFPREG(rs2) + 1]);
B
blueswir1 已提交
4088 4089
                    break;
                case 0x07d: /* VIS I fors */
B
blueswir1 已提交
4090
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4091
                    tcg_gen_or_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
B
blueswir1 已提交
4092
                    break;
4093
                case 0x07e: /* VIS I fone */
B
blueswir1 已提交
4094
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4095 4096
                    tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], -1);
                    tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], -1);
4097 4098
                    break;
                case 0x07f: /* VIS I fones */
B
blueswir1 已提交
4099
                    CHECK_FPU_FEATURE(dc, VIS1);
B
blueswir1 已提交
4100
                    tcg_gen_movi_i32(cpu_fpr[rd], -1);
4101
                    break;
B
blueswir1 已提交
4102 4103 4104 4105
                case 0x080: /* VIS I shutdown */
                case 0x081: /* VIS II siam */
                    // XXX
                    goto illegal_insn;
4106 4107 4108 4109
                default:
                    goto illegal_insn;
                }
#else
B
blueswir1 已提交
4110
                goto ncp_insn;
4111 4112
#endif
            } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
4113
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4114
                goto illegal_insn;
4115
#else
B
blueswir1 已提交
4116
                goto ncp_insn;
4117
#endif
B
bellard 已提交
4118
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4119
            } else if (xop == 0x39) { /* V9 return */
P
pbrook 已提交
4120
                TCGv_i32 r_const;
B
blueswir1 已提交
4121

4122
                save_state(dc, cpu_cond);
4123
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
4124
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
4125 4126
                    simm = GET_FIELDs(insn, 19, 31);
                    tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
B
blueswir1 已提交
4127
                } else {                /* register */
B
bellard 已提交
4128
                    rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
4129
                    if (rs2) {
4130 4131
                        gen_movl_reg_TN(rs2, cpu_src2);
                        tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4132 4133
                    } else
                        tcg_gen_mov_tl(cpu_dst, cpu_src1);
B
bellard 已提交
4134
                }
P
pbrook 已提交
4135
                gen_helper_restore();
4136
                gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
4137
                r_const = tcg_const_i32(3);
P
pbrook 已提交
4138 4139
                gen_helper_check_align(cpu_dst, r_const);
                tcg_temp_free_i32(r_const);
4140
                tcg_gen_mov_tl(cpu_npc, cpu_dst);
B
blueswir1 已提交
4141 4142
                dc->npc = DYNAMIC_PC;
                goto jmp_insn;
B
bellard 已提交
4143
#endif
B
blueswir1 已提交
4144
            } else {
4145
                cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
4146
                if (IS_IMM) {   /* immediate */
B
Blue Swirl 已提交
4147 4148
                    simm = GET_FIELDs(insn, 19, 31);
                    tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
B
blueswir1 已提交
4149
                } else {                /* register */
B
bellard 已提交
4150
                    rs2 = GET_FIELD(insn, 27, 31);
B
blueswir1 已提交
4151
                    if (rs2) {
4152 4153
                        gen_movl_reg_TN(rs2, cpu_src2);
                        tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4154 4155
                    } else
                        tcg_gen_mov_tl(cpu_dst, cpu_src1);
4156
                }
B
blueswir1 已提交
4157 4158 4159
                switch (xop) {
                case 0x38:      /* jmpl */
                    {
P
pbrook 已提交
4160 4161
                        TCGv r_pc;
                        TCGv_i32 r_const;
B
blueswir1 已提交
4162

P
pbrook 已提交
4163 4164 4165
                        r_pc = tcg_const_tl(dc->pc);
                        gen_movl_TN_reg(rd, r_pc);
                        tcg_temp_free(r_pc);
4166
                        gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
4167
                        r_const = tcg_const_i32(3);
P
pbrook 已提交
4168 4169
                        gen_helper_check_align(cpu_dst, r_const);
                        tcg_temp_free_i32(r_const);
4170
                        tcg_gen_mov_tl(cpu_npc, cpu_dst);
B
blueswir1 已提交
4171 4172 4173
                        dc->npc = DYNAMIC_PC;
                    }
                    goto jmp_insn;
B
bellard 已提交
4174
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
B
blueswir1 已提交
4175 4176
                case 0x39:      /* rett, V9 return */
                    {
P
pbrook 已提交
4177
                        TCGv_i32 r_const;
B
blueswir1 已提交
4178

B
blueswir1 已提交
4179 4180
                        if (!supervisor(dc))
                            goto priv_insn;
4181
                        gen_mov_pc_npc(dc, cpu_cond);
B
blueswir1 已提交
4182
                        r_const = tcg_const_i32(3);
P
pbrook 已提交
4183 4184
                        gen_helper_check_align(cpu_dst, r_const);
                        tcg_temp_free_i32(r_const);
4185
                        tcg_gen_mov_tl(cpu_npc, cpu_dst);
B
blueswir1 已提交
4186
                        dc->npc = DYNAMIC_PC;
P
pbrook 已提交
4187
                        gen_helper_rett();
B
blueswir1 已提交
4188 4189 4190 4191
                    }
                    goto jmp_insn;
#endif
                case 0x3b: /* flush */
4192
                    if (!((dc)->def->features & CPU_FEATURE_FLUSH))
B
blueswir1 已提交
4193
                        goto unimp_flush;
P
pbrook 已提交
4194
                    gen_helper_flush(cpu_dst);
B
blueswir1 已提交
4195 4196
                    break;
                case 0x3c:      /* save */
4197
                    save_state(dc, cpu_cond);
P
pbrook 已提交
4198
                    gen_helper_save();
4199
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4200 4201
                    break;
                case 0x3d:      /* restore */
4202
                    save_state(dc, cpu_cond);
P
pbrook 已提交
4203
                    gen_helper_restore();
4204
                    gen_movl_TN_reg(rd, cpu_dst);
B
blueswir1 已提交
4205
                    break;
B
bellard 已提交
4206
#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
B
blueswir1 已提交
4207 4208 4209 4210 4211 4212 4213 4214
                case 0x3e:      /* V9 done/retry */
                    {
                        switch (rd) {
                        case 0:
                            if (!supervisor(dc))
                                goto priv_insn;
                            dc->npc = DYNAMIC_PC;
                            dc->pc = DYNAMIC_PC;
P
pbrook 已提交
4215
                            gen_helper_done();
B
blueswir1 已提交
4216 4217 4218 4219 4220 4221
                            goto jmp_insn;
                        case 1:
                            if (!supervisor(dc))
                                goto priv_insn;
                            dc->npc = DYNAMIC_PC;
                            dc->pc = DYNAMIC_PC;
P
pbrook 已提交
4222
                            gen_helper_retry();
B
blueswir1 已提交
4223 4224 4225 4226 4227 4228 4229 4230 4231 4232
                            goto jmp_insn;
                        default:
                            goto illegal_insn;
                        }
                    }
                    break;
#endif
                default:
                    goto illegal_insn;
                }
4233
            }
B
blueswir1 已提交
4234 4235 4236 4237 4238 4239
            break;
        }
        break;
    case 3:                     /* load/store instructions */
        {
            unsigned int xop = GET_FIELD(insn, 7, 12);
4240

4241 4242 4243 4244 4245 4246
            /* flush pending conditional evaluations before exposing
               cpu state */
            if (dc->cc_op != CC_OP_FLAGS) {
                dc->cc_op = CC_OP_FLAGS;
                gen_helper_compute_psr();
            }
4247
            cpu_src1 = get_src1(insn, cpu_src1);
B
blueswir1 已提交
4248
            if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
4249
                rs2 = GET_FIELD(insn, 27, 31);
4250
                gen_movl_reg_TN(rs2, cpu_src2);
B
blueswir1 已提交
4251 4252
                tcg_gen_mov_tl(cpu_addr, cpu_src1);
            } else if (IS_IMM) {     /* immediate */
B
Blue Swirl 已提交
4253 4254
                simm = GET_FIELDs(insn, 19, 31);
                tcg_gen_addi_tl(cpu_addr, cpu_src1, simm);
B
blueswir1 已提交
4255 4256 4257
            } else {            /* register */
                rs2 = GET_FIELD(insn, 27, 31);
                if (rs2 != 0) {
4258 4259
                    gen_movl_reg_TN(rs2, cpu_src2);
                    tcg_gen_add_tl(cpu_addr, cpu_src1, cpu_src2);
4260 4261
                } else
                    tcg_gen_mov_tl(cpu_addr, cpu_src1);
B
blueswir1 已提交
4262
            }
B
blueswir1 已提交
4263 4264 4265
            if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
                (xop > 0x17 && xop <= 0x1d ) ||
                (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
B
blueswir1 已提交
4266
                switch (xop) {
4267
                case 0x0:       /* ld, V9 lduw, load unsigned word */
B
blueswir1 已提交
4268
                    gen_address_mask(dc, cpu_addr);
4269
                    tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4270
                    break;
4271
                case 0x1:       /* ldub, load unsigned byte */
B
blueswir1 已提交
4272
                    gen_address_mask(dc, cpu_addr);
4273
                    tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4274
                    break;
4275
                case 0x2:       /* lduh, load unsigned halfword */
B
blueswir1 已提交
4276
                    gen_address_mask(dc, cpu_addr);
4277
                    tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4278
                    break;
4279
                case 0x3:       /* ldd, load double word */
B
blueswir1 已提交
4280
                    if (rd & 1)
4281
                        goto illegal_insn;
B
blueswir1 已提交
4282
                    else {
P
pbrook 已提交
4283
                        TCGv_i32 r_const;
B
blueswir1 已提交
4284

4285
                        save_state(dc, cpu_cond);
B
blueswir1 已提交
4286
                        r_const = tcg_const_i32(7);
P
pbrook 已提交
4287 4288
                        gen_helper_check_align(cpu_addr, r_const); // XXX remove
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4289
                        gen_address_mask(dc, cpu_addr);
4290
                        tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
4291 4292 4293
                        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 已提交
4294
                        tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
4295 4296
                        tcg_gen_trunc_i64_tl(cpu_val, cpu_tmp64);
                        tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL);
B
blueswir1 已提交
4297
                    }
B
blueswir1 已提交
4298
                    break;
4299
                case 0x9:       /* ldsb, load signed byte */
B
blueswir1 已提交
4300
                    gen_address_mask(dc, cpu_addr);
4301
                    tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4302
                    break;
4303
                case 0xa:       /* ldsh, load signed halfword */
B
blueswir1 已提交
4304
                    gen_address_mask(dc, cpu_addr);
4305
                    tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4306 4307
                    break;
                case 0xd:       /* ldstub -- XXX: should be atomically */
B
blueswir1 已提交
4308 4309 4310
                    {
                        TCGv r_const;

B
blueswir1 已提交
4311
                        gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4312 4313 4314 4315 4316
                        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 已提交
4317
                    break;
4318
                case 0x0f:      /* swap, swap register with memory. Also
B
blueswir1 已提交
4319
                                   atomically */
B
blueswir1 已提交
4320
                    CHECK_IU_FEATURE(dc, SWAP);
4321
                    gen_movl_reg_TN(rd, cpu_val);
B
blueswir1 已提交
4322
                    gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4323
                    tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
4324
                    tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4325
                    tcg_gen_mov_tl(cpu_val, cpu_tmp0);
B
blueswir1 已提交
4326
                    break;
B
bellard 已提交
4327
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
4328
                case 0x10:      /* lda, V9 lduwa, load word alternate */
B
bellard 已提交
4329
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4330 4331 4332 4333
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4334
#endif
4335
                    save_state(dc, cpu_cond);
4336
                    gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
B
blueswir1 已提交
4337
                    break;
4338
                case 0x11:      /* lduba, load unsigned byte alternate */
B
bellard 已提交
4339
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4340 4341 4342 4343 4344
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
4345
                    save_state(dc, cpu_cond);
4346
                    gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
B
blueswir1 已提交
4347
                    break;
4348
                case 0x12:      /* lduha, load unsigned halfword alternate */
B
bellard 已提交
4349
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4350 4351 4352 4353
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4354
#endif
4355
                    save_state(dc, cpu_cond);
4356
                    gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
B
blueswir1 已提交
4357
                    break;
4358
                case 0x13:      /* ldda, load double word alternate */
B
bellard 已提交
4359
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4360 4361 4362 4363
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4364
#endif
B
blueswir1 已提交
4365
                    if (rd & 1)
4366
                        goto illegal_insn;
4367
                    save_state(dc, cpu_cond);
B
blueswir1 已提交
4368 4369
                    gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
                    goto skip_move;
4370
                case 0x19:      /* ldsba, load signed byte alternate */
B
bellard 已提交
4371
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4372 4373 4374 4375 4376
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
4377
                    save_state(dc, cpu_cond);
4378
                    gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
B
blueswir1 已提交
4379
                    break;
4380
                case 0x1a:      /* ldsha, load signed halfword alternate */
B
bellard 已提交
4381
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4382 4383 4384 4385
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4386
#endif
4387
                    save_state(dc, cpu_cond);
4388
                    gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
B
blueswir1 已提交
4389 4390
                    break;
                case 0x1d:      /* ldstuba -- XXX: should be atomically */
B
bellard 已提交
4391
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4392 4393 4394 4395 4396
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
#endif
4397
                    save_state(dc, cpu_cond);
4398
                    gen_ldstub_asi(cpu_val, cpu_addr, insn);
B
blueswir1 已提交
4399
                    break;
4400
                case 0x1f:      /* swapa, swap reg with alt. memory. Also
B
blueswir1 已提交
4401
                                   atomically */
B
blueswir1 已提交
4402
                    CHECK_IU_FEATURE(dc, SWAP);
B
bellard 已提交
4403
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4404 4405 4406 4407
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4408
#endif
4409
                    save_state(dc, cpu_cond);
4410 4411
                    gen_movl_reg_TN(rd, cpu_val);
                    gen_swap_asi(cpu_val, cpu_addr, insn);
B
blueswir1 已提交
4412
                    break;
B
bellard 已提交
4413 4414

#ifndef TARGET_SPARC64
B
blueswir1 已提交
4415 4416 4417 4418
                case 0x30: /* ldc */
                case 0x31: /* ldcsr */
                case 0x33: /* lddc */
                    goto ncp_insn;
B
bellard 已提交
4419 4420 4421
#endif
#endif
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4422
                case 0x08: /* V9 ldsw */
B
blueswir1 已提交
4423
                    gen_address_mask(dc, cpu_addr);
4424
                    tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4425 4426
                    break;
                case 0x0b: /* V9 ldx */
B
blueswir1 已提交
4427
                    gen_address_mask(dc, cpu_addr);
4428
                    tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4429 4430
                    break;
                case 0x18: /* V9 ldswa */
4431
                    save_state(dc, cpu_cond);
4432
                    gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
B
blueswir1 已提交
4433 4434
                    break;
                case 0x1b: /* V9 ldxa */
4435
                    save_state(dc, cpu_cond);
4436
                    gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
B
blueswir1 已提交
4437 4438 4439 4440
                    break;
                case 0x2d: /* V9 prefetch, no effect */
                    goto skip_move;
                case 0x30: /* V9 ldfa */
4441
                    save_state(dc, cpu_cond);
4442
                    gen_ldf_asi(cpu_addr, insn, 4, rd);
4443
                    goto skip_move;
B
blueswir1 已提交
4444
                case 0x33: /* V9 lddfa */
4445
                    save_state(dc, cpu_cond);
4446
                    gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
4447
                    goto skip_move;
B
blueswir1 已提交
4448 4449 4450
                case 0x3d: /* V9 prefetcha, no effect */
                    goto skip_move;
                case 0x32: /* V9 ldqfa */
B
blueswir1 已提交
4451
                    CHECK_FPU_FEATURE(dc, FLOAT128);
4452
                    save_state(dc, cpu_cond);
4453
                    gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
B
blueswir1 已提交
4454
                    goto skip_move;
B
blueswir1 已提交
4455 4456 4457 4458
#endif
                default:
                    goto illegal_insn;
                }
4459
                gen_movl_TN_reg(rd, cpu_val);
B
blueswir1 已提交
4460
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
B
blueswir1 已提交
4461
            skip_move: ;
B
bellard 已提交
4462
#endif
B
blueswir1 已提交
4463
            } else if (xop >= 0x20 && xop < 0x24) {
4464
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
4465
                    goto jmp_insn;
4466
                save_state(dc, cpu_cond);
B
blueswir1 已提交
4467
                switch (xop) {
4468
                case 0x20:      /* ldf, load fpreg */
B
blueswir1 已提交
4469
                    gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4470 4471
                    tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
                    tcg_gen_trunc_tl_i32(cpu_fpr[rd], cpu_tmp0);
B
blueswir1 已提交
4472
                    break;
4473 4474
                case 0x21:      /* ldfsr, V9 ldxfsr */
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4475
                    gen_address_mask(dc, cpu_addr);
4476 4477
                    if (rd == 1) {
                        tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
P
pbrook 已提交
4478
                        gen_helper_ldxfsr(cpu_tmp64);
4479 4480 4481 4482
                    } else
#else
                    {
                        tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
P
pbrook 已提交
4483
                        gen_helper_ldfsr(cpu_tmp32);
4484 4485
                    }
#endif
B
blueswir1 已提交
4486
                    break;
4487
                case 0x22:      /* ldqf, load quad fpreg */
B
blueswir1 已提交
4488
                    {
P
pbrook 已提交
4489
                        TCGv_i32 r_const;
B
blueswir1 已提交
4490 4491 4492

                        CHECK_FPU_FEATURE(dc, FLOAT128);
                        r_const = tcg_const_i32(dc->mem_idx);
P
pbrook 已提交
4493 4494
                        gen_helper_ldqf(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4495 4496
                        gen_op_store_QT0_fpr(QFPREG(rd));
                    }
B
blueswir1 已提交
4497
                    break;
4498
                case 0x23:      /* lddf, load double fpreg */
B
blueswir1 已提交
4499
                    {
P
pbrook 已提交
4500
                        TCGv_i32 r_const;
B
blueswir1 已提交
4501 4502

                        r_const = tcg_const_i32(dc->mem_idx);
P
pbrook 已提交
4503 4504
                        gen_helper_lddf(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4505 4506
                        gen_op_store_DT0_fpr(DFPREG(rd));
                    }
B
blueswir1 已提交
4507 4508 4509 4510
                    break;
                default:
                    goto illegal_insn;
                }
B
Blue Swirl 已提交
4511
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
B
blueswir1 已提交
4512
                       xop == 0xe || xop == 0x1e) {
4513
                gen_movl_reg_TN(rd, cpu_val);
B
blueswir1 已提交
4514
                switch (xop) {
4515
                case 0x4: /* st, store word */
B
blueswir1 已提交
4516
                    gen_address_mask(dc, cpu_addr);
4517
                    tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4518
                    break;
4519
                case 0x5: /* stb, store byte */
B
blueswir1 已提交
4520
                    gen_address_mask(dc, cpu_addr);
4521
                    tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4522
                    break;
4523
                case 0x6: /* sth, store halfword */
B
blueswir1 已提交
4524
                    gen_address_mask(dc, cpu_addr);
4525
                    tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4526
                    break;
4527
                case 0x7: /* std, store double word */
B
blueswir1 已提交
4528
                    if (rd & 1)
4529
                        goto illegal_insn;
B
blueswir1 已提交
4530
                    else {
P
pbrook 已提交
4531
                        TCGv_i32 r_const;
B
blueswir1 已提交
4532

4533
                        save_state(dc, cpu_cond);
B
blueswir1 已提交
4534
                        gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4535
                        r_const = tcg_const_i32(7);
P
pbrook 已提交
4536 4537
                        gen_helper_check_align(cpu_addr, r_const); // XXX remove
                        tcg_temp_free_i32(r_const);
4538
                        gen_movl_reg_TN(rd + 1, cpu_tmp0);
4539
                        tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
4540
                        tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4541
                    }
B
blueswir1 已提交
4542
                    break;
B
bellard 已提交
4543
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
4544
                case 0x14: /* sta, V9 stwa, store word alternate */
B
bellard 已提交
4545
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4546 4547 4548 4549
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4550
#endif
4551
                    save_state(dc, cpu_cond);
4552
                    gen_st_asi(cpu_val, cpu_addr, insn, 4);
4553
                    dc->npc = DYNAMIC_PC;
B
bellard 已提交
4554
                    break;
4555
                case 0x15: /* stba, store byte alternate */
B
bellard 已提交
4556
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4557 4558 4559 4560
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4561
#endif
4562
                    save_state(dc, cpu_cond);
4563
                    gen_st_asi(cpu_val, cpu_addr, insn, 1);
4564
                    dc->npc = DYNAMIC_PC;
B
bellard 已提交
4565
                    break;
4566
                case 0x16: /* stha, store halfword alternate */
B
bellard 已提交
4567
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4568 4569 4570 4571
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
blueswir1 已提交
4572
#endif
4573
                    save_state(dc, cpu_cond);
4574
                    gen_st_asi(cpu_val, cpu_addr, insn, 2);
4575
                    dc->npc = DYNAMIC_PC;
B
bellard 已提交
4576
                    break;
4577
                case 0x17: /* stda, store double word alternate */
B
bellard 已提交
4578
#ifndef TARGET_SPARC64
B
blueswir1 已提交
4579 4580 4581 4582
                    if (IS_IMM)
                        goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
B
bellard 已提交
4583
#endif
B
blueswir1 已提交
4584
                    if (rd & 1)
4585
                        goto illegal_insn;
B
blueswir1 已提交
4586
                    else {
4587
                        save_state(dc, cpu_cond);
4588
                        gen_stda_asi(cpu_val, cpu_addr, insn, rd);
B
blueswir1 已提交
4589
                    }
B
bellard 已提交
4590
                    break;
B
bellard 已提交
4591
#endif
B
bellard 已提交
4592
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4593
                case 0x0e: /* V9 stx */
B
blueswir1 已提交
4594
                    gen_address_mask(dc, cpu_addr);
4595
                    tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4596 4597
                    break;
                case 0x1e: /* V9 stxa */
4598
                    save_state(dc, cpu_cond);
4599
                    gen_st_asi(cpu_val, cpu_addr, insn, 8);
4600
                    dc->npc = DYNAMIC_PC;
B
blueswir1 已提交
4601
                    break;
B
bellard 已提交
4602
#endif
B
blueswir1 已提交
4603 4604 4605 4606
                default:
                    goto illegal_insn;
                }
            } else if (xop > 0x23 && xop < 0x28) {
4607
                if (gen_trap_ifnofpu(dc, cpu_cond))
B
bellard 已提交
4608
                    goto jmp_insn;
4609
                save_state(dc, cpu_cond);
B
blueswir1 已提交
4610
                switch (xop) {
4611
                case 0x24: /* stf, store fpreg */
B
blueswir1 已提交
4612
                    gen_address_mask(dc, cpu_addr);
B
blueswir1 已提交
4613 4614
                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_fpr[rd]);
                    tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx);
B
blueswir1 已提交
4615 4616
                    break;
                case 0x25: /* stfsr, V9 stxfsr */
4617
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4618
                    gen_address_mask(dc, cpu_addr);
4619 4620 4621
                    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 已提交
4622 4623
                    else
                        tcg_gen_qemu_st32(cpu_tmp64, cpu_addr, dc->mem_idx);
4624 4625
#else
                    tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUState, fsr));
4626
                    tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
4627
#endif
B
blueswir1 已提交
4628
                    break;
B
blueswir1 已提交
4629 4630 4631
                case 0x26:
#ifdef TARGET_SPARC64
                    /* V9 stqf, store quad fpreg */
B
blueswir1 已提交
4632
                    {
P
pbrook 已提交
4633
                        TCGv_i32 r_const;
B
blueswir1 已提交
4634 4635 4636 4637

                        CHECK_FPU_FEATURE(dc, FLOAT128);
                        gen_op_load_fpr_QT0(QFPREG(rd));
                        r_const = tcg_const_i32(dc->mem_idx);
P
pbrook 已提交
4638 4639
                        gen_helper_stqf(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4640
                    }
B
blueswir1 已提交
4641 4642 4643 4644 4645 4646
                    break;
#else /* !TARGET_SPARC64 */
                    /* stdfq, store floating point queue */
#if defined(CONFIG_USER_ONLY)
                    goto illegal_insn;
#else
B
blueswir1 已提交
4647 4648
                    if (!supervisor(dc))
                        goto priv_insn;
4649
                    if (gen_trap_ifnofpu(dc, cpu_cond))
B
blueswir1 已提交
4650 4651
                        goto jmp_insn;
                    goto nfq_insn;
B
blueswir1 已提交
4652
#endif
B
blueswir1 已提交
4653
#endif
4654
                case 0x27: /* stdf, store double fpreg */
B
blueswir1 已提交
4655
                    {
P
pbrook 已提交
4656
                        TCGv_i32 r_const;
B
blueswir1 已提交
4657 4658 4659

                        gen_op_load_fpr_DT0(DFPREG(rd));
                        r_const = tcg_const_i32(dc->mem_idx);
P
pbrook 已提交
4660 4661
                        gen_helper_stdf(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4662
                    }
B
blueswir1 已提交
4663 4664 4665 4666 4667
                    break;
                default:
                    goto illegal_insn;
                }
            } else if (xop > 0x33 && xop < 0x3f) {
4668
                save_state(dc, cpu_cond);
B
blueswir1 已提交
4669
                switch (xop) {
4670
#ifdef TARGET_SPARC64
B
blueswir1 已提交
4671
                case 0x34: /* V9 stfa */
4672
                    gen_stf_asi(cpu_addr, insn, 4, rd);
B
blueswir1 已提交
4673
                    break;
B
blueswir1 已提交
4674
                case 0x36: /* V9 stqfa */
B
blueswir1 已提交
4675
                    {
P
pbrook 已提交
4676
                        TCGv_i32 r_const;
B
blueswir1 已提交
4677 4678 4679

                        CHECK_FPU_FEATURE(dc, FLOAT128);
                        r_const = tcg_const_i32(7);
P
pbrook 已提交
4680 4681
                        gen_helper_check_align(cpu_addr, r_const);
                        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4682 4683 4684
                        gen_op_load_fpr_QT0(QFPREG(rd));
                        gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
                    }
B
blueswir1 已提交
4685
                    break;
B
blueswir1 已提交
4686
                case 0x37: /* V9 stdfa */
4687
                    gen_op_load_fpr_DT0(DFPREG(rd));
4688
                    gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
B
blueswir1 已提交
4689 4690
                    break;
                case 0x3c: /* V9 casa */
B
blueswir1 已提交
4691
                    gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
4692
                    gen_movl_TN_reg(rd, cpu_val);
B
blueswir1 已提交
4693 4694
                    break;
                case 0x3e: /* V9 casxa */
B
blueswir1 已提交
4695
                    gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
4696
                    gen_movl_TN_reg(rd, cpu_val);
B
blueswir1 已提交
4697
                    break;
4698
#else
B
blueswir1 已提交
4699 4700 4701 4702 4703 4704 4705 4706 4707
                case 0x34: /* stc */
                case 0x35: /* stcsr */
                case 0x36: /* stdcq */
                case 0x37: /* stdc */
                    goto ncp_insn;
#endif
                default:
                    goto illegal_insn;
                }
B
Blue Swirl 已提交
4708
            } else
B
blueswir1 已提交
4709 4710 4711
                goto illegal_insn;
        }
        break;
4712 4713
    }
    /* default case for non jump instructions */
B
bellard 已提交
4714
    if (dc->npc == DYNAMIC_PC) {
B
blueswir1 已提交
4715 4716
        dc->pc = DYNAMIC_PC;
        gen_op_next_insn();
B
bellard 已提交
4717 4718
    } else if (dc->npc == JUMP_PC) {
        /* we can do a static jump */
4719
        gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
B
bellard 已提交
4720 4721
        dc->is_br = 1;
    } else {
B
blueswir1 已提交
4722 4723
        dc->pc = dc->npc;
        dc->npc = dc->npc + 4;
4724
    }
B
bellard 已提交
4725
 jmp_insn:
4726
    goto egress;
4727
 illegal_insn:
B
blueswir1 已提交
4728
    {
P
pbrook 已提交
4729
        TCGv_i32 r_const;
B
blueswir1 已提交
4730 4731 4732

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_ILL_INSN);
P
pbrook 已提交
4733 4734
        gen_helper_raise_exception(r_const);
        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4735 4736
        dc->is_br = 1;
    }
4737
    goto egress;
B
blueswir1 已提交
4738
 unimp_flush:
B
blueswir1 已提交
4739
    {
P
pbrook 已提交
4740
        TCGv_i32 r_const;
B
blueswir1 已提交
4741 4742 4743

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_UNIMP_FLUSH);
P
pbrook 已提交
4744 4745
        gen_helper_raise_exception(r_const);
        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4746 4747
        dc->is_br = 1;
    }
4748
    goto egress;
B
bellard 已提交
4749
#if !defined(CONFIG_USER_ONLY)
4750
 priv_insn:
B
blueswir1 已提交
4751
    {
P
pbrook 已提交
4752
        TCGv_i32 r_const;
B
blueswir1 已提交
4753 4754 4755

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_PRIV_INSN);
P
pbrook 已提交
4756 4757
        gen_helper_raise_exception(r_const);
        tcg_temp_free_i32(r_const);
B
blueswir1 已提交
4758 4759
        dc->is_br = 1;
    }
4760
    goto egress;
B
blueswir1 已提交
4761
#endif
B
bellard 已提交
4762
 nfpu_insn:
4763
    save_state(dc, cpu_cond);
B
bellard 已提交
4764 4765
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
    dc->is_br = 1;
4766
    goto egress;
B
blueswir1 已提交
4767
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
B
blueswir1 已提交
4768
 nfq_insn:
4769
    save_state(dc, cpu_cond);
B
blueswir1 已提交
4770 4771
    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
    dc->is_br = 1;
4772
    goto egress;
B
blueswir1 已提交
4773
#endif
4774 4775
#ifndef TARGET_SPARC64
 ncp_insn:
B
blueswir1 已提交
4776 4777 4778 4779 4780
    {
        TCGv r_const;

        save_state(dc, cpu_cond);
        r_const = tcg_const_i32(TT_NCP_INSN);
P
pbrook 已提交
4781
        gen_helper_raise_exception(r_const);
B
blueswir1 已提交
4782 4783 4784
        tcg_temp_free(r_const);
        dc->is_br = 1;
    }
4785
    goto egress;
4786
#endif
4787 4788 4789
 egress:
    tcg_temp_free(cpu_tmp1);
    tcg_temp_free(cpu_tmp2);
4790 4791
}

4792 4793
static inline void gen_intermediate_code_internal(TranslationBlock * tb,
                                                  int spc, CPUSPARCState *env)
4794
{
B
bellard 已提交
4795
    target_ulong pc_start, last_pc;
4796 4797
    uint16_t *gen_opc_end;
    DisasContext dc1, *dc = &dc1;
4798
    CPUBreakpoint *bp;
4799
    int j, lj = -1;
P
pbrook 已提交
4800 4801
    int num_insns;
    int max_insns;
4802 4803 4804

    memset(dc, 0, sizeof(DisasContext));
    dc->tb = tb;
B
bellard 已提交
4805
    pc_start = tb->pc;
4806
    dc->pc = pc_start;
B
bellard 已提交
4807
    last_pc = dc->pc;
B
bellard 已提交
4808
    dc->npc = (target_ulong) tb->cs_base;
4809
    dc->cc_op = CC_OP_DYNAMIC;
B
blueswir1 已提交
4810
    dc->mem_idx = cpu_mmu_index(env);
4811 4812
    dc->def = env->def;
    if ((dc->def->features & CPU_FEATURE_FLOAT))
B
blueswir1 已提交
4813
        dc->fpu_enabled = cpu_fpu_enabled(env);
4814
    else
B
blueswir1 已提交
4815
        dc->fpu_enabled = 0;
B
blueswir1 已提交
4816 4817 4818
#ifdef TARGET_SPARC64
    dc->address_mask_32bit = env->pstate & PS_AM;
#endif
4819
    dc->singlestep = (env->singlestep_enabled || singlestep);
4820 4821
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

P
pbrook 已提交
4822 4823 4824
    cpu_tmp0 = tcg_temp_new();
    cpu_tmp32 = tcg_temp_new_i32();
    cpu_tmp64 = tcg_temp_new_i64();
B
blueswir1 已提交
4825

P
pbrook 已提交
4826
    cpu_dst = tcg_temp_local_new();
B
blueswir1 已提交
4827 4828

    // loads and stores
P
pbrook 已提交
4829 4830
    cpu_val = tcg_temp_local_new();
    cpu_addr = tcg_temp_local_new();
B
blueswir1 已提交
4831

P
pbrook 已提交
4832 4833 4834 4835 4836
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;
    gen_icount_start();
4837
    do {
B
Blue Swirl 已提交
4838 4839
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
4840
                if (bp->pc == dc->pc) {
B
blueswir1 已提交
4841
                    if (dc->pc != pc_start)
4842
                        save_state(dc, cpu_cond);
P
pbrook 已提交
4843
                    gen_helper_debug();
B
bellard 已提交
4844
                    tcg_gen_exit_tb(0);
B
blueswir1 已提交
4845
                    dc->is_br = 1;
B
bellard 已提交
4846
                    goto exit_gen_loop;
4847 4848 4849 4850
                }
            }
        }
        if (spc) {
4851
            qemu_log("Search PC...\n");
4852 4853 4854 4855 4856 4857 4858 4859
            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 已提交
4860
                gen_opc_icount[lj] = num_insns;
4861 4862
            }
        }
P
pbrook 已提交
4863 4864
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
B
blueswir1 已提交
4865 4866
        last_pc = dc->pc;
        disas_sparc_insn(dc);
P
pbrook 已提交
4867
        num_insns++;
B
blueswir1 已提交
4868 4869 4870 4871 4872 4873

        if (dc->is_br)
            break;
        /* if the next PC is different, we abort now */
        if (dc->pc != (last_pc + 4))
            break;
B
bellard 已提交
4874 4875 4876 4877
        /* 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 已提交
4878 4879
        /* if single step mode, we generate only one instruction and
           generate an exception */
4880
        if (dc->singlestep) {
B
bellard 已提交
4881 4882
            break;
        }
4883
    } while ((gen_opc_ptr < gen_opc_end) &&
P
pbrook 已提交
4884 4885
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
             num_insns < max_insns);
B
bellard 已提交
4886 4887

 exit_gen_loop:
B
blueswir1 已提交
4888
    tcg_temp_free(cpu_addr);
B
blueswir1 已提交
4889
    tcg_temp_free(cpu_val);
B
blueswir1 已提交
4890
    tcg_temp_free(cpu_dst);
P
pbrook 已提交
4891 4892
    tcg_temp_free_i64(cpu_tmp64);
    tcg_temp_free_i32(cpu_tmp32);
B
blueswir1 已提交
4893
    tcg_temp_free(cpu_tmp0);
P
pbrook 已提交
4894 4895
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
B
bellard 已提交
4896
    if (!dc->is_br) {
4897
        if (dc->pc != DYNAMIC_PC &&
B
bellard 已提交
4898 4899
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
            /* static PC and NPC: we can use direct chaining */
B
blueswir1 已提交
4900
            gen_goto_tb(dc, 0, dc->pc, dc->npc);
B
bellard 已提交
4901 4902
        } else {
            if (dc->pc != DYNAMIC_PC)
B
blueswir1 已提交
4903
                tcg_gen_movi_tl(cpu_pc, dc->pc);
4904
            save_npc(dc, cpu_cond);
B
bellard 已提交
4905
            tcg_gen_exit_tb(0);
B
bellard 已提交
4906 4907
        }
    }
P
pbrook 已提交
4908
    gen_icount_end(tb, num_insns);
4909
    *gen_opc_ptr = INDEX_op_end;
4910 4911 4912 4913 4914 4915
    if (spc) {
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
#if 0
4916
        log_page_dump();
4917
#endif
4918 4919
        gen_opc_jump_pc[0] = dc->jump_pc[0];
        gen_opc_jump_pc[1] = dc->jump_pc[1];
4920
    } else {
B
bellard 已提交
4921
        tb->size = last_pc + 4 - pc_start;
P
pbrook 已提交
4922
        tb->icount = num_insns;
4923
    }
4924
#ifdef DEBUG_DISAS
4925
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
4926 4927 4928 4929
        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");
4930
    }
4931 4932 4933
#endif
}

4934
void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
4935
{
4936
    gen_intermediate_code_internal(tb, 0, env);
4937 4938
}

4939
void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
4940
{
4941
    gen_intermediate_code_internal(tb, 1, env);
4942 4943
}

4944
void gen_intermediate_code_init(CPUSPARCState *env)
B
bellard 已提交
4945
{
B
blueswir1 已提交
4946
    unsigned int i;
4947
    static int inited;
B
blueswir1 已提交
4948 4949 4950 4951 4952 4953 4954 4955 4956 4957
    static const char * const gregnames[8] = {
        NULL, // g0 not used
        "g1",
        "g2",
        "g3",
        "g4",
        "g5",
        "g6",
        "g7",
    };
B
blueswir1 已提交
4958 4959 4960 4961 4962 4963 4964 4965 4966 4967
    static const char * const fregnames[64] = {
        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
        "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
        "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
        "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
        "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
        "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
        "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
        "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
    };
B
bellard 已提交
4968

B
blueswir1 已提交
4969 4970 4971 4972
    /* init various static tables */
    if (!inited) {
        inited = 1;

P
pbrook 已提交
4973 4974 4975 4976
        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 已提交
4977
#ifdef TARGET_SPARC64
P
pbrook 已提交
4978 4979 4980 4981 4982 4983 4984
        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),
4985
                                     "gsr");
P
pbrook 已提交
4986
        cpu_tick_cmpr = tcg_global_mem_new(TCG_AREG0,
4987 4988
                                           offsetof(CPUState, tick_cmpr),
                                           "tick_cmpr");
P
pbrook 已提交
4989
        cpu_stick_cmpr = tcg_global_mem_new(TCG_AREG0,
4990 4991
                                            offsetof(CPUState, stick_cmpr),
                                            "stick_cmpr");
P
pbrook 已提交
4992
        cpu_hstick_cmpr = tcg_global_mem_new(TCG_AREG0,
4993 4994
                                             offsetof(CPUState, hstick_cmpr),
                                             "hstick_cmpr");
P
pbrook 已提交
4995
        cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, hintp),
4996
                                       "hintp");
P
pbrook 已提交
4997 4998 4999 5000 5001
        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,
5002
                                     offsetof(CPUState, ssr), "ssr");
P
pbrook 已提交
5003
        cpu_ver = tcg_global_mem_new(TCG_AREG0,
5004
                                     offsetof(CPUState, version), "ver");
P
pbrook 已提交
5005 5006 5007
        cpu_softint = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, softint),
                                             "softint");
5008
#else
P
pbrook 已提交
5009
        cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, wim),
5010
                                     "wim");
B
blueswir1 已提交
5011
#endif
P
pbrook 已提交
5012
        cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cond),
B
blueswir1 已提交
5013
                                      "cond");
P
pbrook 已提交
5014
        cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src),
5015
                                        "cc_src");
P
pbrook 已提交
5016
        cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0,
B
blueswir1 已提交
5017 5018
                                         offsetof(CPUState, cc_src2),
                                         "cc_src2");
P
pbrook 已提交
5019
        cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst),
5020
                                        "cc_dst");
5021 5022
        cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, cc_op),
                                           "cc_op");
P
pbrook 已提交
5023 5024 5025
        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 已提交
5026
                                     "fsr");
P
pbrook 已提交
5027
        cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, pc),
B
blueswir1 已提交
5028
                                    "pc");
P
pbrook 已提交
5029 5030 5031
        cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, npc),
                                     "npc");
        cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, y), "y");
5032
#ifndef CONFIG_USER_ONLY
P
pbrook 已提交
5033
        cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, tbr),
5034 5035
                                     "tbr");
#endif
B
blueswir1 已提交
5036
        for (i = 1; i < 8; i++)
P
pbrook 已提交
5037
            cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
B
blueswir1 已提交
5038 5039
                                              offsetof(CPUState, gregs[i]),
                                              gregnames[i]);
B
blueswir1 已提交
5040
        for (i = 0; i < TARGET_FPREGS; i++)
P
pbrook 已提交
5041 5042 5043
            cpu_fpr[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                                offsetof(CPUState, fpr[i]),
                                                fregnames[i]);
B
blueswir1 已提交
5044

B
blueswir1 已提交
5045 5046
        /* register helpers */

P
pbrook 已提交
5047
#define GEN_HELPER 2
B
blueswir1 已提交
5048
#include "helper.h"
B
blueswir1 已提交
5049
    }
B
bellard 已提交
5050
}
A
aurel32 已提交
5051 5052 5053 5054 5055 5056 5057 5058 5059 5060

void gen_pc_load(CPUState *env, TranslationBlock *tb,
                unsigned long searched_pc, int pc_pos, void *puc)
{
    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 已提交
5061 5062
        /* jump PC: use 'cond' and the jump targets of the translation */
        if (env->cond) {
A
aurel32 已提交
5063
            env->npc = gen_opc_jump_pc[0];
B
Blue Swirl 已提交
5064
        } else {
A
aurel32 已提交
5065
            env->npc = gen_opc_jump_pc[1];
B
Blue Swirl 已提交
5066
        }
A
aurel32 已提交
5067 5068 5069
    } else {
        env->npc = npc;
    }
5070 5071 5072 5073 5074

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