]> git.proxmox.com Git - mirror_qemu.git/blame - target-sparc/translate.c
target-sparc: Unify asi handling between 32 and 64-bit
[mirror_qemu.git] / target-sparc / translate.c
CommitLineData
7a3f1944
FB
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
3475187d 5 Copyright (C) 2003-2005 Fabrice Bellard
7a3f1944
FB
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
8167ee88 18 License along with this library; if not, see <http://www.gnu.org/licenses/>.
7a3f1944
FB
19 */
20
db5ebe5f 21#include "qemu/osdep.h"
7a3f1944
FB
22
23#include "cpu.h"
76cad711 24#include "disas/disas.h"
2ef6175a 25#include "exec/helper-proto.h"
63c91552 26#include "exec/exec-all.h"
57fec1fe 27#include "tcg-op.h"
f08b6170 28#include "exec/cpu_ldst.h"
7a3f1944 29
2ef6175a 30#include "exec/helper-gen.h"
a7812ae4 31
a7e30d84 32#include "trace-tcg.h"
508127e2 33#include "exec/log.h"
a7e30d84
LV
34
35
7a3f1944
FB
36#define DEBUG_DISAS
37
72cbca10
FB
38#define DYNAMIC_PC 1 /* dynamic pc value */
39#define JUMP_PC 2 /* dynamic pc value which takes only two values
40 according to jump_pc[T2] */
41
1a2fb1c0 42/* global register indexes */
1bcea73e
LV
43static TCGv_env cpu_env;
44static TCGv_ptr cpu_regwptr;
25517f99
PB
45static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
46static TCGv_i32 cpu_cc_op;
a7812ae4 47static TCGv_i32 cpu_psr;
d2dc4069
RH
48static TCGv cpu_fsr, cpu_pc, cpu_npc;
49static TCGv cpu_regs[32];
255e1fcb
BS
50static TCGv cpu_y;
51#ifndef CONFIG_USER_ONLY
52static TCGv cpu_tbr;
53#endif
5793f2a4 54static TCGv cpu_cond;
dc99a3f2 55#ifdef TARGET_SPARC64
a7812ae4
PB
56static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs;
57static TCGv cpu_gsr;
255e1fcb 58static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
a7812ae4 59static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
255e1fcb
BS
60#else
61static TCGv cpu_wim;
dc99a3f2 62#endif
714547bb 63/* Floating point registers */
30038fd8 64static TCGv_i64 cpu_fpr[TARGET_DPREGS];
1a2fb1c0 65
022c62cb 66#include "exec/gen-icount.h"
2e70f6ef 67
7a3f1944 68typedef struct DisasContext {
0f8a249a
BS
69 target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
70 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
72cbca10 71 target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
cf495bcf 72 int is_br;
e8af50a3 73 int mem_idx;
a80dde08 74 int fpu_enabled;
2cade6a3 75 int address_mask_32bit;
060718c1 76 int singlestep;
8393617c 77 uint32_t cc_op; /* current CC operation */
cf495bcf 78 struct TranslationBlock *tb;
5578ceab 79 sparc_def_t *def;
30038fd8 80 TCGv_i32 t32[3];
88023616 81 TCGv ttl[5];
30038fd8 82 int n_t32;
88023616 83 int n_ttl;
7a3f1944
FB
84} DisasContext;
85
416fcaea
RH
86typedef struct {
87 TCGCond cond;
88 bool is_bool;
89 bool g1, g2;
90 TCGv c1, c2;
91} DisasCompare;
92
3475187d 93// This function uses non-native bit order
dc1a6971
BS
94#define GET_FIELD(X, FROM, TO) \
95 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
7a3f1944 96
3475187d 97// This function uses the order in the manuals, i.e. bit 0 is 2^0
dc1a6971 98#define GET_FIELD_SP(X, FROM, TO) \
3475187d
FB
99 GET_FIELD(X, 31 - (TO), 31 - (FROM))
100
101#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
46d38ba8 102#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
3475187d
FB
103
104#ifdef TARGET_SPARC64
0387d928 105#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
1f587329 106#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
3475187d 107#else
c185970a 108#define DFPREG(r) (r & 0x1e)
1f587329 109#define QFPREG(r) (r & 0x1c)
3475187d
FB
110#endif
111
b158a785
BS
112#define UA2005_HTRAP_MASK 0xff
113#define V8_TRAP_MASK 0x7f
114
3475187d
FB
115static int sign_extend(int x, int len)
116{
117 len = 32 - len;
118 return (x << len) >> len;
119}
120
7a3f1944
FB
121#define IS_IMM (insn & (1<<13))
122
2ae23e17
RH
123static inline TCGv_i32 get_temp_i32(DisasContext *dc)
124{
125 TCGv_i32 t;
126 assert(dc->n_t32 < ARRAY_SIZE(dc->t32));
127 dc->t32[dc->n_t32++] = t = tcg_temp_new_i32();
128 return t;
129}
130
131static inline TCGv get_temp_tl(DisasContext *dc)
132{
133 TCGv t;
134 assert(dc->n_ttl < ARRAY_SIZE(dc->ttl));
135 dc->ttl[dc->n_ttl++] = t = tcg_temp_new();
136 return t;
137}
138
141ae5c1
RH
139static inline void gen_update_fprs_dirty(int rd)
140{
141#if defined(TARGET_SPARC64)
142 tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2);
143#endif
144}
145
ff07ec83 146/* floating point registers moves */
208ae657
RH
147static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
148{
30038fd8
RH
149#if TCG_TARGET_REG_BITS == 32
150 if (src & 1) {
151 return TCGV_LOW(cpu_fpr[src / 2]);
152 } else {
153 return TCGV_HIGH(cpu_fpr[src / 2]);
154 }
155#else
156 if (src & 1) {
157 return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2]));
158 } else {
2ae23e17 159 TCGv_i32 ret = get_temp_i32(dc);
30038fd8
RH
160 TCGv_i64 t = tcg_temp_new_i64();
161
162 tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32);
ecc7b3aa 163 tcg_gen_extrl_i64_i32(ret, t);
30038fd8
RH
164 tcg_temp_free_i64(t);
165
30038fd8
RH
166 return ret;
167 }
168#endif
208ae657
RH
169}
170
171static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
172{
30038fd8
RH
173#if TCG_TARGET_REG_BITS == 32
174 if (dst & 1) {
175 tcg_gen_mov_i32(TCGV_LOW(cpu_fpr[dst / 2]), v);
176 } else {
177 tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr[dst / 2]), v);
178 }
179#else
180 TCGv_i64 t = MAKE_TCGV_I64(GET_TCGV_I32(v));
181 tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
182 (dst & 1 ? 0 : 32), 32);
183#endif
141ae5c1 184 gen_update_fprs_dirty(dst);
208ae657
RH
185}
186
ba5f5179 187static TCGv_i32 gen_dest_fpr_F(DisasContext *dc)
208ae657 188{
ba5f5179 189 return get_temp_i32(dc);
208ae657
RH
190}
191
96eda024
RH
192static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
193{
96eda024 194 src = DFPREG(src);
30038fd8 195 return cpu_fpr[src / 2];
96eda024
RH
196}
197
198static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
199{
200 dst = DFPREG(dst);
30038fd8 201 tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
96eda024
RH
202 gen_update_fprs_dirty(dst);
203}
204
3886b8a3 205static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
96eda024 206{
3886b8a3 207 return cpu_fpr[DFPREG(dst) / 2];
96eda024
RH
208}
209
ff07ec83
BS
210static void gen_op_load_fpr_QT0(unsigned int src)
211{
30038fd8
RH
212 tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
213 offsetof(CPU_QuadU, ll.upper));
214 tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
215 offsetof(CPU_QuadU, ll.lower));
ff07ec83
BS
216}
217
218static void gen_op_load_fpr_QT1(unsigned int src)
219{
30038fd8
RH
220 tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt1) +
221 offsetof(CPU_QuadU, ll.upper));
222 tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
223 offsetof(CPU_QuadU, ll.lower));
ff07ec83
BS
224}
225
226static void gen_op_store_QT0_fpr(unsigned int dst)
227{
30038fd8
RH
228 tcg_gen_ld_i64(cpu_fpr[dst / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
229 offsetof(CPU_QuadU, ll.upper));
230 tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
231 offsetof(CPU_QuadU, ll.lower));
ff07ec83 232}
1f587329 233
ac11f776 234#ifdef TARGET_SPARC64
30038fd8 235static void gen_move_Q(unsigned int rd, unsigned int rs)
ac11f776
RH
236{
237 rd = QFPREG(rd);
238 rs = QFPREG(rs);
239
30038fd8
RH
240 tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
241 tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
ac11f776
RH
242 gen_update_fprs_dirty(rd);
243}
244#endif
245
81ad8ba2
BS
246/* moves */
247#ifdef CONFIG_USER_ONLY
3475187d 248#define supervisor(dc) 0
81ad8ba2 249#ifdef TARGET_SPARC64
e9ebed4d 250#define hypervisor(dc) 0
81ad8ba2 251#endif
3475187d 252#else
2aae2b8e 253#define supervisor(dc) (dc->mem_idx >= MMU_KERNEL_IDX)
81ad8ba2 254#ifdef TARGET_SPARC64
2aae2b8e 255#define hypervisor(dc) (dc->mem_idx == MMU_HYPV_IDX)
6f27aba6 256#else
3475187d 257#endif
81ad8ba2
BS
258#endif
259
2cade6a3
BS
260#ifdef TARGET_SPARC64
261#ifndef TARGET_ABI32
262#define AM_CHECK(dc) ((dc)->address_mask_32bit)
1a2fb1c0 263#else
2cade6a3
BS
264#define AM_CHECK(dc) (1)
265#endif
1a2fb1c0 266#endif
3391c818 267
2cade6a3
BS
268static inline void gen_address_mask(DisasContext *dc, TCGv addr)
269{
270#ifdef TARGET_SPARC64
271 if (AM_CHECK(dc))
272 tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
273#endif
274}
275
88023616
RH
276static inline TCGv gen_load_gpr(DisasContext *dc, int reg)
277{
d2dc4069
RH
278 if (reg > 0) {
279 assert(reg < 32);
280 return cpu_regs[reg];
281 } else {
88023616 282 TCGv t = get_temp_tl(dc);
d2dc4069 283 tcg_gen_movi_tl(t, 0);
88023616 284 return t;
88023616
RH
285 }
286}
287
288static inline void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
289{
290 if (reg > 0) {
d2dc4069
RH
291 assert(reg < 32);
292 tcg_gen_mov_tl(cpu_regs[reg], v);
88023616
RH
293 }
294}
295
296static inline TCGv gen_dest_gpr(DisasContext *dc, int reg)
297{
d2dc4069
RH
298 if (reg > 0) {
299 assert(reg < 32);
300 return cpu_regs[reg];
88023616 301 } else {
d2dc4069 302 return get_temp_tl(dc);
88023616
RH
303 }
304}
305
90aa39a1
SF
306static inline bool use_goto_tb(DisasContext *s, target_ulong pc,
307 target_ulong npc)
308{
309 if (unlikely(s->singlestep)) {
310 return false;
311 }
312
313#ifndef CONFIG_USER_ONLY
314 return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) &&
315 (npc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK);
316#else
317 return true;
318#endif
319}
320
5fafdf24 321static inline void gen_goto_tb(DisasContext *s, int tb_num,
6e256c93
FB
322 target_ulong pc, target_ulong npc)
323{
90aa39a1 324 if (use_goto_tb(s, pc, npc)) {
6e256c93 325 /* jump to same page: we can use a direct jump */
57fec1fe 326 tcg_gen_goto_tb(tb_num);
2f5680ee
BS
327 tcg_gen_movi_tl(cpu_pc, pc);
328 tcg_gen_movi_tl(cpu_npc, npc);
90aa39a1 329 tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
6e256c93
FB
330 } else {
331 /* jump to another page: currently not optimized */
2f5680ee
BS
332 tcg_gen_movi_tl(cpu_pc, pc);
333 tcg_gen_movi_tl(cpu_npc, npc);
57fec1fe 334 tcg_gen_exit_tb(0);
6e256c93
FB
335 }
336}
337
19f329ad 338// XXX suboptimal
a7812ae4 339static inline void gen_mov_reg_N(TCGv reg, TCGv_i32 src)
19f329ad 340{
8911f501 341 tcg_gen_extu_i32_tl(reg, src);
4b8b8b76 342 tcg_gen_shri_tl(reg, reg, PSR_NEG_SHIFT);
19f329ad
BS
343 tcg_gen_andi_tl(reg, reg, 0x1);
344}
345
a7812ae4 346static inline void gen_mov_reg_Z(TCGv reg, TCGv_i32 src)
19f329ad 347{
8911f501 348 tcg_gen_extu_i32_tl(reg, src);
4b8b8b76 349 tcg_gen_shri_tl(reg, reg, PSR_ZERO_SHIFT);
19f329ad
BS
350 tcg_gen_andi_tl(reg, reg, 0x1);
351}
352
a7812ae4 353static inline void gen_mov_reg_V(TCGv reg, TCGv_i32 src)
19f329ad 354{
8911f501 355 tcg_gen_extu_i32_tl(reg, src);
4b8b8b76 356 tcg_gen_shri_tl(reg, reg, PSR_OVF_SHIFT);
19f329ad
BS
357 tcg_gen_andi_tl(reg, reg, 0x1);
358}
359
a7812ae4 360static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src)
19f329ad 361{
8911f501 362 tcg_gen_extu_i32_tl(reg, src);
4b8b8b76 363 tcg_gen_shri_tl(reg, reg, PSR_CARRY_SHIFT);
19f329ad
BS
364 tcg_gen_andi_tl(reg, reg, 0x1);
365}
366
4af984a7 367static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
dc99a3f2 368{
4af984a7 369 tcg_gen_mov_tl(cpu_cc_src, src1);
6f551262 370 tcg_gen_mov_tl(cpu_cc_src2, src2);
5c6a0628 371 tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
bdf9f35d 372 tcg_gen_mov_tl(dst, cpu_cc_dst);
41d72852
BS
373}
374
70c48285 375static TCGv_i32 gen_add32_carry32(void)
dc99a3f2 376{
70c48285
RH
377 TCGv_i32 carry_32, cc_src1_32, cc_src2_32;
378
379 /* Carry is computed from a previous add: (dst < src) */
380#if TARGET_LONG_BITS == 64
381 cc_src1_32 = tcg_temp_new_i32();
382 cc_src2_32 = tcg_temp_new_i32();
ecc7b3aa
RH
383 tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_dst);
384 tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src);
70c48285
RH
385#else
386 cc_src1_32 = cpu_cc_dst;
387 cc_src2_32 = cpu_cc_src;
388#endif
389
390 carry_32 = tcg_temp_new_i32();
391 tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);
392
393#if TARGET_LONG_BITS == 64
394 tcg_temp_free_i32(cc_src1_32);
395 tcg_temp_free_i32(cc_src2_32);
396#endif
397
398 return carry_32;
41d72852
BS
399}
400
70c48285 401static TCGv_i32 gen_sub32_carry32(void)
41d72852 402{
70c48285
RH
403 TCGv_i32 carry_32, cc_src1_32, cc_src2_32;
404
405 /* Carry is computed from a previous borrow: (src1 < src2) */
406#if TARGET_LONG_BITS == 64
407 cc_src1_32 = tcg_temp_new_i32();
408 cc_src2_32 = tcg_temp_new_i32();
ecc7b3aa
RH
409 tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_src);
410 tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src2);
70c48285
RH
411#else
412 cc_src1_32 = cpu_cc_src;
413 cc_src2_32 = cpu_cc_src2;
414#endif
415
416 carry_32 = tcg_temp_new_i32();
417 tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);
418
419#if TARGET_LONG_BITS == 64
420 tcg_temp_free_i32(cc_src1_32);
421 tcg_temp_free_i32(cc_src2_32);
422#endif
423
424 return carry_32;
425}
426
427static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
428 TCGv src2, int update_cc)
429{
430 TCGv_i32 carry_32;
431 TCGv carry;
432
433 switch (dc->cc_op) {
434 case CC_OP_DIV:
435 case CC_OP_LOGIC:
436 /* Carry is known to be zero. Fall back to plain ADD. */
437 if (update_cc) {
438 gen_op_add_cc(dst, src1, src2);
439 } else {
440 tcg_gen_add_tl(dst, src1, src2);
441 }
442 return;
443
444 case CC_OP_ADD:
445 case CC_OP_TADD:
446 case CC_OP_TADDTV:
15fe216f
RH
447 if (TARGET_LONG_BITS == 32) {
448 /* We can re-use the host's hardware carry generation by using
449 an ADD2 opcode. We discard the low part of the output.
450 Ideally we'd combine this operation with the add that
451 generated the carry in the first place. */
452 carry = tcg_temp_new();
453 tcg_gen_add2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
454 tcg_temp_free(carry);
70c48285
RH
455 goto add_done;
456 }
70c48285
RH
457 carry_32 = gen_add32_carry32();
458 break;
459
460 case CC_OP_SUB:
461 case CC_OP_TSUB:
462 case CC_OP_TSUBTV:
463 carry_32 = gen_sub32_carry32();
464 break;
465
466 default:
467 /* We need external help to produce the carry. */
468 carry_32 = tcg_temp_new_i32();
2ffd9176 469 gen_helper_compute_C_icc(carry_32, cpu_env);
70c48285
RH
470 break;
471 }
472
473#if TARGET_LONG_BITS == 64
474 carry = tcg_temp_new();
475 tcg_gen_extu_i32_i64(carry, carry_32);
476#else
477 carry = carry_32;
478#endif
479
480 tcg_gen_add_tl(dst, src1, src2);
481 tcg_gen_add_tl(dst, dst, carry);
482
483 tcg_temp_free_i32(carry_32);
484#if TARGET_LONG_BITS == 64
485 tcg_temp_free(carry);
486#endif
487
70c48285 488 add_done:
70c48285
RH
489 if (update_cc) {
490 tcg_gen_mov_tl(cpu_cc_src, src1);
491 tcg_gen_mov_tl(cpu_cc_src2, src2);
492 tcg_gen_mov_tl(cpu_cc_dst, dst);
493 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
494 dc->cc_op = CC_OP_ADDX;
495 }
dc99a3f2
BS
496}
497
41d72852 498static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
dc99a3f2 499{
4af984a7 500 tcg_gen_mov_tl(cpu_cc_src, src1);
6f551262 501 tcg_gen_mov_tl(cpu_cc_src2, src2);
41d72852 502 tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
d4b0d468 503 tcg_gen_mov_tl(dst, cpu_cc_dst);
41d72852
BS
504}
505
70c48285
RH
506static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
507 TCGv src2, int update_cc)
41d72852 508{
70c48285
RH
509 TCGv_i32 carry_32;
510 TCGv carry;
41d72852 511
70c48285
RH
512 switch (dc->cc_op) {
513 case CC_OP_DIV:
514 case CC_OP_LOGIC:
515 /* Carry is known to be zero. Fall back to plain SUB. */
516 if (update_cc) {
517 gen_op_sub_cc(dst, src1, src2);
518 } else {
519 tcg_gen_sub_tl(dst, src1, src2);
520 }
521 return;
522
523 case CC_OP_ADD:
524 case CC_OP_TADD:
525 case CC_OP_TADDTV:
526 carry_32 = gen_add32_carry32();
527 break;
528
529 case CC_OP_SUB:
530 case CC_OP_TSUB:
531 case CC_OP_TSUBTV:
15fe216f
RH
532 if (TARGET_LONG_BITS == 32) {
533 /* We can re-use the host's hardware carry generation by using
534 a SUB2 opcode. We discard the low part of the output.
535 Ideally we'd combine this operation with the add that
536 generated the carry in the first place. */
537 carry = tcg_temp_new();
538 tcg_gen_sub2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
539 tcg_temp_free(carry);
70c48285
RH
540 goto sub_done;
541 }
70c48285
RH
542 carry_32 = gen_sub32_carry32();
543 break;
544
545 default:
546 /* We need external help to produce the carry. */
547 carry_32 = tcg_temp_new_i32();
2ffd9176 548 gen_helper_compute_C_icc(carry_32, cpu_env);
70c48285
RH
549 break;
550 }
551
552#if TARGET_LONG_BITS == 64
553 carry = tcg_temp_new();
554 tcg_gen_extu_i32_i64(carry, carry_32);
555#else
556 carry = carry_32;
557#endif
558
559 tcg_gen_sub_tl(dst, src1, src2);
560 tcg_gen_sub_tl(dst, dst, carry);
561
562 tcg_temp_free_i32(carry_32);
563#if TARGET_LONG_BITS == 64
564 tcg_temp_free(carry);
565#endif
566
70c48285 567 sub_done:
70c48285
RH
568 if (update_cc) {
569 tcg_gen_mov_tl(cpu_cc_src, src1);
570 tcg_gen_mov_tl(cpu_cc_src2, src2);
571 tcg_gen_mov_tl(cpu_cc_dst, dst);
572 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
573 dc->cc_op = CC_OP_SUBX;
574 }
dc99a3f2
BS
575}
576
4af984a7 577static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
d9bdab86 578{
de9e9d9f 579 TCGv r_temp, zero, t0;
d9bdab86 580
a7812ae4 581 r_temp = tcg_temp_new();
de9e9d9f 582 t0 = tcg_temp_new();
d9bdab86
BS
583
584 /* old op:
585 if (!(env->y & 1))
586 T1 = 0;
587 */
6cb675b0 588 zero = tcg_const_tl(0);
72ccba79 589 tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
255e1fcb 590 tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
72ccba79 591 tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
6cb675b0
RH
592 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero,
593 zero, cpu_cc_src2);
594 tcg_temp_free(zero);
d9bdab86
BS
595
596 // b2 = T0 & 1;
597 // env->y = (b2 << 31) | (env->y >> 1);
105a1f04
BS
598 tcg_gen_andi_tl(r_temp, cpu_cc_src, 0x1);
599 tcg_gen_shli_tl(r_temp, r_temp, 31);
de9e9d9f
RH
600 tcg_gen_shri_tl(t0, cpu_y, 1);
601 tcg_gen_andi_tl(t0, t0, 0x7fffffff);
602 tcg_gen_or_tl(t0, t0, r_temp);
603 tcg_gen_andi_tl(cpu_y, t0, 0xffffffff);
d9bdab86
BS
604
605 // b1 = N ^ V;
de9e9d9f 606 gen_mov_reg_N(t0, cpu_psr);
d9bdab86 607 gen_mov_reg_V(r_temp, cpu_psr);
de9e9d9f 608 tcg_gen_xor_tl(t0, t0, r_temp);
2ea815ca 609 tcg_temp_free(r_temp);
d9bdab86
BS
610
611 // T0 = (b1 << 31) | (T0 >> 1);
612 // src1 = T0;
de9e9d9f 613 tcg_gen_shli_tl(t0, t0, 31);
6f551262 614 tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1);
de9e9d9f
RH
615 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
616 tcg_temp_free(t0);
d9bdab86 617
5c6a0628 618 tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
d9bdab86 619
5c6a0628 620 tcg_gen_mov_tl(dst, cpu_cc_dst);
d9bdab86
BS
621}
622
fb170183 623static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
8879d139 624{
528692a8 625#if TARGET_LONG_BITS == 32
fb170183 626 if (sign_ext) {
528692a8 627 tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
fb170183 628 } else {
528692a8 629 tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
fb170183 630 }
528692a8
RH
631#else
632 TCGv t0 = tcg_temp_new_i64();
633 TCGv t1 = tcg_temp_new_i64();
fb170183 634
528692a8
RH
635 if (sign_ext) {
636 tcg_gen_ext32s_i64(t0, src1);
637 tcg_gen_ext32s_i64(t1, src2);
638 } else {
639 tcg_gen_ext32u_i64(t0, src1);
640 tcg_gen_ext32u_i64(t1, src2);
641 }
fb170183 642
528692a8
RH
643 tcg_gen_mul_i64(dst, t0, t1);
644 tcg_temp_free(t0);
645 tcg_temp_free(t1);
fb170183 646
528692a8
RH
647 tcg_gen_shri_i64(cpu_y, dst, 32);
648#endif
8879d139
BS
649}
650
fb170183 651static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
8879d139 652{
fb170183
IK
653 /* zero-extend truncated operands before multiplication */
654 gen_op_multiply(dst, src1, src2, 0);
655}
8879d139 656
fb170183
IK
657static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
658{
659 /* sign-extend truncated operands before multiplication */
660 gen_op_multiply(dst, src1, src2, 1);
8879d139
BS
661}
662
19f329ad
BS
663// 1
664static inline void gen_op_eval_ba(TCGv dst)
665{
666 tcg_gen_movi_tl(dst, 1);
667}
668
669// Z
a7812ae4 670static inline void gen_op_eval_be(TCGv dst, TCGv_i32 src)
19f329ad
BS
671{
672 gen_mov_reg_Z(dst, src);
673}
674
675// Z | (N ^ V)
a7812ae4 676static inline void gen_op_eval_ble(TCGv dst, TCGv_i32 src)
19f329ad 677{
de9e9d9f
RH
678 TCGv t0 = tcg_temp_new();
679 gen_mov_reg_N(t0, src);
19f329ad 680 gen_mov_reg_V(dst, src);
de9e9d9f
RH
681 tcg_gen_xor_tl(dst, dst, t0);
682 gen_mov_reg_Z(t0, src);
683 tcg_gen_or_tl(dst, dst, t0);
684 tcg_temp_free(t0);
19f329ad
BS
685}
686
687// N ^ V
a7812ae4 688static inline void gen_op_eval_bl(TCGv dst, TCGv_i32 src)
19f329ad 689{
de9e9d9f
RH
690 TCGv t0 = tcg_temp_new();
691 gen_mov_reg_V(t0, src);
19f329ad 692 gen_mov_reg_N(dst, src);
de9e9d9f
RH
693 tcg_gen_xor_tl(dst, dst, t0);
694 tcg_temp_free(t0);
19f329ad
BS
695}
696
697// C | Z
a7812ae4 698static inline void gen_op_eval_bleu(TCGv dst, TCGv_i32 src)
19f329ad 699{
de9e9d9f
RH
700 TCGv t0 = tcg_temp_new();
701 gen_mov_reg_Z(t0, src);
19f329ad 702 gen_mov_reg_C(dst, src);
de9e9d9f
RH
703 tcg_gen_or_tl(dst, dst, t0);
704 tcg_temp_free(t0);
19f329ad
BS
705}
706
707// C
a7812ae4 708static inline void gen_op_eval_bcs(TCGv dst, TCGv_i32 src)
19f329ad
BS
709{
710 gen_mov_reg_C(dst, src);
711}
712
713// V
a7812ae4 714static inline void gen_op_eval_bvs(TCGv dst, TCGv_i32 src)
19f329ad
BS
715{
716 gen_mov_reg_V(dst, src);
717}
718
719// 0
720static inline void gen_op_eval_bn(TCGv dst)
721{
722 tcg_gen_movi_tl(dst, 0);
723}
724
725// N
a7812ae4 726static inline void gen_op_eval_bneg(TCGv dst, TCGv_i32 src)
19f329ad
BS
727{
728 gen_mov_reg_N(dst, src);
729}
730
731// !Z
a7812ae4 732static inline void gen_op_eval_bne(TCGv dst, TCGv_i32 src)
19f329ad
BS
733{
734 gen_mov_reg_Z(dst, src);
735 tcg_gen_xori_tl(dst, dst, 0x1);
736}
737
738// !(Z | (N ^ V))
a7812ae4 739static inline void gen_op_eval_bg(TCGv dst, TCGv_i32 src)
19f329ad 740{
de9e9d9f 741 gen_op_eval_ble(dst, src);
19f329ad
BS
742 tcg_gen_xori_tl(dst, dst, 0x1);
743}
744
745// !(N ^ V)
a7812ae4 746static inline void gen_op_eval_bge(TCGv dst, TCGv_i32 src)
19f329ad 747{
de9e9d9f 748 gen_op_eval_bl(dst, src);
19f329ad
BS
749 tcg_gen_xori_tl(dst, dst, 0x1);
750}
751
752// !(C | Z)
a7812ae4 753static inline void gen_op_eval_bgu(TCGv dst, TCGv_i32 src)
19f329ad 754{
de9e9d9f 755 gen_op_eval_bleu(dst, src);
19f329ad
BS
756 tcg_gen_xori_tl(dst, dst, 0x1);
757}
758
759// !C
a7812ae4 760static inline void gen_op_eval_bcc(TCGv dst, TCGv_i32 src)
19f329ad
BS
761{
762 gen_mov_reg_C(dst, src);
763 tcg_gen_xori_tl(dst, dst, 0x1);
764}
765
766// !N
a7812ae4 767static inline void gen_op_eval_bpos(TCGv dst, TCGv_i32 src)
19f329ad
BS
768{
769 gen_mov_reg_N(dst, src);
770 tcg_gen_xori_tl(dst, dst, 0x1);
771}
772
773// !V
a7812ae4 774static inline void gen_op_eval_bvc(TCGv dst, TCGv_i32 src)
19f329ad
BS
775{
776 gen_mov_reg_V(dst, src);
777 tcg_gen_xori_tl(dst, dst, 0x1);
778}
779
780/*
781 FPSR bit field FCC1 | FCC0:
782 0 =
783 1 <
784 2 >
785 3 unordered
786*/
787static inline void gen_mov_reg_FCC0(TCGv reg, TCGv src,
788 unsigned int fcc_offset)
789{
ba6a9d8c 790 tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset);
19f329ad
BS
791 tcg_gen_andi_tl(reg, reg, 0x1);
792}
793
794static inline void gen_mov_reg_FCC1(TCGv reg, TCGv src,
795 unsigned int fcc_offset)
796{
ba6a9d8c 797 tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset);
19f329ad
BS
798 tcg_gen_andi_tl(reg, reg, 0x1);
799}
800
801// !0: FCC0 | FCC1
802static inline void gen_op_eval_fbne(TCGv dst, TCGv src,
803 unsigned int fcc_offset)
804{
de9e9d9f 805 TCGv t0 = tcg_temp_new();
19f329ad 806 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
807 gen_mov_reg_FCC1(t0, src, fcc_offset);
808 tcg_gen_or_tl(dst, dst, t0);
809 tcg_temp_free(t0);
19f329ad
BS
810}
811
812// 1 or 2: FCC0 ^ FCC1
813static inline void gen_op_eval_fblg(TCGv dst, TCGv src,
814 unsigned int fcc_offset)
815{
de9e9d9f 816 TCGv t0 = tcg_temp_new();
19f329ad 817 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
818 gen_mov_reg_FCC1(t0, src, fcc_offset);
819 tcg_gen_xor_tl(dst, dst, t0);
820 tcg_temp_free(t0);
19f329ad
BS
821}
822
823// 1 or 3: FCC0
824static inline void gen_op_eval_fbul(TCGv dst, TCGv src,
825 unsigned int fcc_offset)
826{
827 gen_mov_reg_FCC0(dst, src, fcc_offset);
828}
829
830// 1: FCC0 & !FCC1
831static inline void gen_op_eval_fbl(TCGv dst, TCGv src,
832 unsigned int fcc_offset)
833{
de9e9d9f 834 TCGv t0 = tcg_temp_new();
19f329ad 835 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
836 gen_mov_reg_FCC1(t0, src, fcc_offset);
837 tcg_gen_andc_tl(dst, dst, t0);
838 tcg_temp_free(t0);
19f329ad
BS
839}
840
841// 2 or 3: FCC1
842static inline void gen_op_eval_fbug(TCGv dst, TCGv src,
843 unsigned int fcc_offset)
844{
845 gen_mov_reg_FCC1(dst, src, fcc_offset);
846}
847
848// 2: !FCC0 & FCC1
849static inline void gen_op_eval_fbg(TCGv dst, TCGv src,
850 unsigned int fcc_offset)
851{
de9e9d9f 852 TCGv t0 = tcg_temp_new();
19f329ad 853 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
854 gen_mov_reg_FCC1(t0, src, fcc_offset);
855 tcg_gen_andc_tl(dst, t0, dst);
856 tcg_temp_free(t0);
19f329ad
BS
857}
858
859// 3: FCC0 & FCC1
860static inline void gen_op_eval_fbu(TCGv dst, TCGv src,
861 unsigned int fcc_offset)
862{
de9e9d9f 863 TCGv t0 = tcg_temp_new();
19f329ad 864 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
865 gen_mov_reg_FCC1(t0, src, fcc_offset);
866 tcg_gen_and_tl(dst, dst, t0);
867 tcg_temp_free(t0);
19f329ad
BS
868}
869
870// 0: !(FCC0 | FCC1)
871static inline void gen_op_eval_fbe(TCGv dst, TCGv src,
872 unsigned int fcc_offset)
873{
de9e9d9f 874 TCGv t0 = tcg_temp_new();
19f329ad 875 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
876 gen_mov_reg_FCC1(t0, src, fcc_offset);
877 tcg_gen_or_tl(dst, dst, t0);
19f329ad 878 tcg_gen_xori_tl(dst, dst, 0x1);
de9e9d9f 879 tcg_temp_free(t0);
19f329ad
BS
880}
881
882// 0 or 3: !(FCC0 ^ FCC1)
883static inline void gen_op_eval_fbue(TCGv dst, TCGv src,
884 unsigned int fcc_offset)
885{
de9e9d9f 886 TCGv t0 = tcg_temp_new();
19f329ad 887 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
888 gen_mov_reg_FCC1(t0, src, fcc_offset);
889 tcg_gen_xor_tl(dst, dst, t0);
19f329ad 890 tcg_gen_xori_tl(dst, dst, 0x1);
de9e9d9f 891 tcg_temp_free(t0);
19f329ad
BS
892}
893
894// 0 or 2: !FCC0
895static inline void gen_op_eval_fbge(TCGv dst, TCGv src,
896 unsigned int fcc_offset)
897{
898 gen_mov_reg_FCC0(dst, src, fcc_offset);
899 tcg_gen_xori_tl(dst, dst, 0x1);
900}
901
902// !1: !(FCC0 & !FCC1)
903static inline void gen_op_eval_fbuge(TCGv dst, TCGv src,
904 unsigned int fcc_offset)
905{
de9e9d9f 906 TCGv t0 = tcg_temp_new();
19f329ad 907 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
908 gen_mov_reg_FCC1(t0, src, fcc_offset);
909 tcg_gen_andc_tl(dst, dst, t0);
19f329ad 910 tcg_gen_xori_tl(dst, dst, 0x1);
de9e9d9f 911 tcg_temp_free(t0);
19f329ad
BS
912}
913
914// 0 or 1: !FCC1
915static inline void gen_op_eval_fble(TCGv dst, TCGv src,
916 unsigned int fcc_offset)
917{
918 gen_mov_reg_FCC1(dst, src, fcc_offset);
919 tcg_gen_xori_tl(dst, dst, 0x1);
920}
921
922// !2: !(!FCC0 & FCC1)
923static inline void gen_op_eval_fbule(TCGv dst, TCGv src,
924 unsigned int fcc_offset)
925{
de9e9d9f 926 TCGv t0 = tcg_temp_new();
19f329ad 927 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
928 gen_mov_reg_FCC1(t0, src, fcc_offset);
929 tcg_gen_andc_tl(dst, t0, dst);
19f329ad 930 tcg_gen_xori_tl(dst, dst, 0x1);
de9e9d9f 931 tcg_temp_free(t0);
19f329ad
BS
932}
933
934// !3: !(FCC0 & FCC1)
935static inline void gen_op_eval_fbo(TCGv dst, TCGv src,
936 unsigned int fcc_offset)
937{
de9e9d9f 938 TCGv t0 = tcg_temp_new();
19f329ad 939 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
940 gen_mov_reg_FCC1(t0, src, fcc_offset);
941 tcg_gen_and_tl(dst, dst, t0);
19f329ad 942 tcg_gen_xori_tl(dst, dst, 0x1);
de9e9d9f 943 tcg_temp_free(t0);
19f329ad
BS
944}
945
46525e1f 946static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
19f329ad 947 target_ulong pc2, TCGv r_cond)
83469015 948{
42a268c2 949 TCGLabel *l1 = gen_new_label();
83469015 950
cb63669a 951 tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
83469015 952
6e256c93 953 gen_goto_tb(dc, 0, pc1, pc1 + 4);
83469015
FB
954
955 gen_set_label(l1);
6e256c93 956 gen_goto_tb(dc, 1, pc2, pc2 + 4);
83469015
FB
957}
958
bfa31b76 959static void gen_branch_a(DisasContext *dc, target_ulong pc1)
83469015 960{
42a268c2 961 TCGLabel *l1 = gen_new_label();
bfa31b76 962 target_ulong npc = dc->npc;
83469015 963
bfa31b76 964 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1);
83469015 965
bfa31b76 966 gen_goto_tb(dc, 0, npc, pc1);
83469015
FB
967
968 gen_set_label(l1);
bfa31b76
RH
969 gen_goto_tb(dc, 1, npc + 4, npc + 8);
970
971 dc->is_br = 1;
83469015
FB
972}
973
2bf2e019
RH
974static void gen_branch_n(DisasContext *dc, target_ulong pc1)
975{
976 target_ulong npc = dc->npc;
977
978 if (likely(npc != DYNAMIC_PC)) {
979 dc->pc = npc;
980 dc->jump_pc[0] = pc1;
981 dc->jump_pc[1] = npc + 4;
982 dc->npc = JUMP_PC;
983 } else {
984 TCGv t, z;
985
986 tcg_gen_mov_tl(cpu_pc, cpu_npc);
987
988 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
989 t = tcg_const_tl(pc1);
990 z = tcg_const_tl(0);
991 tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc);
992 tcg_temp_free(t);
993 tcg_temp_free(z);
994
995 dc->pc = DYNAMIC_PC;
996 }
997}
998
2e655fe7 999static inline void gen_generic_branch(DisasContext *dc)
83469015 1000{
61316742
RH
1001 TCGv npc0 = tcg_const_tl(dc->jump_pc[0]);
1002 TCGv npc1 = tcg_const_tl(dc->jump_pc[1]);
1003 TCGv zero = tcg_const_tl(0);
19f329ad 1004
61316742 1005 tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1);
83469015 1006
61316742
RH
1007 tcg_temp_free(npc0);
1008 tcg_temp_free(npc1);
1009 tcg_temp_free(zero);
83469015
FB
1010}
1011
4af984a7
BS
1012/* call this function before using the condition register as it may
1013 have been set for a jump */
dee8913c 1014static inline void flush_cond(DisasContext *dc)
83469015
FB
1015{
1016 if (dc->npc == JUMP_PC) {
2e655fe7 1017 gen_generic_branch(dc);
83469015
FB
1018 dc->npc = DYNAMIC_PC;
1019 }
1020}
1021
934da7ee 1022static inline void save_npc(DisasContext *dc)
72cbca10
FB
1023{
1024 if (dc->npc == JUMP_PC) {
2e655fe7 1025 gen_generic_branch(dc);
72cbca10
FB
1026 dc->npc = DYNAMIC_PC;
1027 } else if (dc->npc != DYNAMIC_PC) {
2f5680ee 1028 tcg_gen_movi_tl(cpu_npc, dc->npc);
72cbca10
FB
1029 }
1030}
1031
20132b96 1032static inline void update_psr(DisasContext *dc)
72cbca10 1033{
cfa90513
BS
1034 if (dc->cc_op != CC_OP_FLAGS) {
1035 dc->cc_op = CC_OP_FLAGS;
2ffd9176 1036 gen_helper_compute_psr(cpu_env);
cfa90513 1037 }
20132b96
RH
1038}
1039
1040static inline void save_state(DisasContext *dc)
1041{
1042 tcg_gen_movi_tl(cpu_pc, dc->pc);
934da7ee 1043 save_npc(dc);
72cbca10
FB
1044}
1045
4fbe0067
RH
1046static void gen_exception(DisasContext *dc, int which)
1047{
1048 TCGv_i32 t;
1049
1050 save_state(dc);
1051 t = tcg_const_i32(which);
1052 gen_helper_raise_exception(cpu_env, t);
1053 tcg_temp_free_i32(t);
1054 dc->is_br = 1;
1055}
1056
13a6dd00 1057static inline void gen_mov_pc_npc(DisasContext *dc)
0bee699e
FB
1058{
1059 if (dc->npc == JUMP_PC) {
2e655fe7 1060 gen_generic_branch(dc);
48d5c82b 1061 tcg_gen_mov_tl(cpu_pc, cpu_npc);
0bee699e
FB
1062 dc->pc = DYNAMIC_PC;
1063 } else if (dc->npc == DYNAMIC_PC) {
48d5c82b 1064 tcg_gen_mov_tl(cpu_pc, cpu_npc);
0bee699e
FB
1065 dc->pc = DYNAMIC_PC;
1066 } else {
1067 dc->pc = dc->npc;
1068 }
1069}
1070
38bc628b
BS
1071static inline void gen_op_next_insn(void)
1072{
48d5c82b
BS
1073 tcg_gen_mov_tl(cpu_pc, cpu_npc);
1074 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
38bc628b
BS
1075}
1076
416fcaea
RH
1077static void free_compare(DisasCompare *cmp)
1078{
1079 if (!cmp->g1) {
1080 tcg_temp_free(cmp->c1);
1081 }
1082 if (!cmp->g2) {
1083 tcg_temp_free(cmp->c2);
1084 }
1085}
1086
2a484ecf 1087static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
416fcaea 1088 DisasContext *dc)
19f329ad 1089{
2a484ecf 1090 static int subcc_cond[16] = {
96b5a3d3 1091 TCG_COND_NEVER,
2a484ecf
RH
1092 TCG_COND_EQ,
1093 TCG_COND_LE,
1094 TCG_COND_LT,
1095 TCG_COND_LEU,
1096 TCG_COND_LTU,
1097 -1, /* neg */
1098 -1, /* overflow */
96b5a3d3 1099 TCG_COND_ALWAYS,
2a484ecf
RH
1100 TCG_COND_NE,
1101 TCG_COND_GT,
1102 TCG_COND_GE,
1103 TCG_COND_GTU,
1104 TCG_COND_GEU,
1105 -1, /* pos */
1106 -1, /* no overflow */
1107 };
1108
96b5a3d3
RH
1109 static int logic_cond[16] = {
1110 TCG_COND_NEVER,
1111 TCG_COND_EQ, /* eq: Z */
1112 TCG_COND_LE, /* le: Z | (N ^ V) -> Z | N */
1113 TCG_COND_LT, /* lt: N ^ V -> N */
1114 TCG_COND_EQ, /* leu: C | Z -> Z */
1115 TCG_COND_NEVER, /* ltu: C -> 0 */
1116 TCG_COND_LT, /* neg: N */
1117 TCG_COND_NEVER, /* vs: V -> 0 */
1118 TCG_COND_ALWAYS,
1119 TCG_COND_NE, /* ne: !Z */
1120 TCG_COND_GT, /* gt: !(Z | (N ^ V)) -> !(Z | N) */
1121 TCG_COND_GE, /* ge: !(N ^ V) -> !N */
1122 TCG_COND_NE, /* gtu: !(C | Z) -> !Z */
1123 TCG_COND_ALWAYS, /* geu: !C -> 1 */
1124 TCG_COND_GE, /* pos: !N */
1125 TCG_COND_ALWAYS, /* vc: !V -> 1 */
1126 };
1127
a7812ae4 1128 TCGv_i32 r_src;
416fcaea
RH
1129 TCGv r_dst;
1130
3475187d 1131#ifdef TARGET_SPARC64
2a484ecf 1132 if (xcc) {
dc99a3f2 1133 r_src = cpu_xcc;
2a484ecf 1134 } else {
dc99a3f2 1135 r_src = cpu_psr;
2a484ecf 1136 }
3475187d 1137#else
dc99a3f2 1138 r_src = cpu_psr;
3475187d 1139#endif
2a484ecf 1140
8393617c 1141 switch (dc->cc_op) {
96b5a3d3
RH
1142 case CC_OP_LOGIC:
1143 cmp->cond = logic_cond[cond];
1144 do_compare_dst_0:
1145 cmp->is_bool = false;
1146 cmp->g2 = false;
1147 cmp->c2 = tcg_const_tl(0);
1148#ifdef TARGET_SPARC64
1149 if (!xcc) {
1150 cmp->g1 = false;
1151 cmp->c1 = tcg_temp_new();
1152 tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst);
1153 break;
1154 }
1155#endif
1156 cmp->g1 = true;
1157 cmp->c1 = cpu_cc_dst;
1158 break;
1159
2a484ecf
RH
1160 case CC_OP_SUB:
1161 switch (cond) {
1162 case 6: /* neg */
1163 case 14: /* pos */
1164 cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE);
96b5a3d3 1165 goto do_compare_dst_0;
2a484ecf 1166
2a484ecf
RH
1167 case 7: /* overflow */
1168 case 15: /* !overflow */
1169 goto do_dynamic;
1170
1171 default:
1172 cmp->cond = subcc_cond[cond];
1173 cmp->is_bool = false;
1174#ifdef TARGET_SPARC64
1175 if (!xcc) {
1176 /* Note that sign-extension works for unsigned compares as
1177 long as both operands are sign-extended. */
1178 cmp->g1 = cmp->g2 = false;
1179 cmp->c1 = tcg_temp_new();
1180 cmp->c2 = tcg_temp_new();
1181 tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src);
1182 tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2);
0fa2a066 1183 break;
2a484ecf
RH
1184 }
1185#endif
1186 cmp->g1 = cmp->g2 = true;
1187 cmp->c1 = cpu_cc_src;
1188 cmp->c2 = cpu_cc_src2;
1189 break;
1190 }
8393617c 1191 break;
2a484ecf 1192
8393617c 1193 default:
2a484ecf 1194 do_dynamic:
2ffd9176 1195 gen_helper_compute_psr(cpu_env);
8393617c 1196 dc->cc_op = CC_OP_FLAGS;
2a484ecf
RH
1197 /* FALLTHRU */
1198
1199 case CC_OP_FLAGS:
1200 /* We're going to generate a boolean result. */
1201 cmp->cond = TCG_COND_NE;
1202 cmp->is_bool = true;
1203 cmp->g1 = cmp->g2 = false;
1204 cmp->c1 = r_dst = tcg_temp_new();
1205 cmp->c2 = tcg_const_tl(0);
1206
1207 switch (cond) {
1208 case 0x0:
1209 gen_op_eval_bn(r_dst);
1210 break;
1211 case 0x1:
1212 gen_op_eval_be(r_dst, r_src);
1213 break;
1214 case 0x2:
1215 gen_op_eval_ble(r_dst, r_src);
1216 break;
1217 case 0x3:
1218 gen_op_eval_bl(r_dst, r_src);
1219 break;
1220 case 0x4:
1221 gen_op_eval_bleu(r_dst, r_src);
1222 break;
1223 case 0x5:
1224 gen_op_eval_bcs(r_dst, r_src);
1225 break;
1226 case 0x6:
1227 gen_op_eval_bneg(r_dst, r_src);
1228 break;
1229 case 0x7:
1230 gen_op_eval_bvs(r_dst, r_src);
1231 break;
1232 case 0x8:
1233 gen_op_eval_ba(r_dst);
1234 break;
1235 case 0x9:
1236 gen_op_eval_bne(r_dst, r_src);
1237 break;
1238 case 0xa:
1239 gen_op_eval_bg(r_dst, r_src);
1240 break;
1241 case 0xb:
1242 gen_op_eval_bge(r_dst, r_src);
1243 break;
1244 case 0xc:
1245 gen_op_eval_bgu(r_dst, r_src);
1246 break;
1247 case 0xd:
1248 gen_op_eval_bcc(r_dst, r_src);
1249 break;
1250 case 0xe:
1251 gen_op_eval_bpos(r_dst, r_src);
1252 break;
1253 case 0xf:
1254 gen_op_eval_bvc(r_dst, r_src);
1255 break;
1256 }
19f329ad
BS
1257 break;
1258 }
1259}
7a3f1944 1260
416fcaea 1261static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
e8af50a3 1262{
19f329ad 1263 unsigned int offset;
416fcaea
RH
1264 TCGv r_dst;
1265
1266 /* For now we still generate a straight boolean result. */
1267 cmp->cond = TCG_COND_NE;
1268 cmp->is_bool = true;
1269 cmp->g1 = cmp->g2 = false;
1270 cmp->c1 = r_dst = tcg_temp_new();
1271 cmp->c2 = tcg_const_tl(0);
19f329ad 1272
19f329ad
BS
1273 switch (cc) {
1274 default:
1275 case 0x0:
1276 offset = 0;
1277 break;
1278 case 0x1:
1279 offset = 32 - 10;
1280 break;
1281 case 0x2:
1282 offset = 34 - 10;
1283 break;
1284 case 0x3:
1285 offset = 36 - 10;
1286 break;
1287 }
1288
1289 switch (cond) {
1290 case 0x0:
1291 gen_op_eval_bn(r_dst);
1292 break;
1293 case 0x1:
87e92502 1294 gen_op_eval_fbne(r_dst, cpu_fsr, offset);
19f329ad
BS
1295 break;
1296 case 0x2:
87e92502 1297 gen_op_eval_fblg(r_dst, cpu_fsr, offset);
19f329ad
BS
1298 break;
1299 case 0x3:
87e92502 1300 gen_op_eval_fbul(r_dst, cpu_fsr, offset);
19f329ad
BS
1301 break;
1302 case 0x4:
87e92502 1303 gen_op_eval_fbl(r_dst, cpu_fsr, offset);
19f329ad
BS
1304 break;
1305 case 0x5:
87e92502 1306 gen_op_eval_fbug(r_dst, cpu_fsr, offset);
19f329ad
BS
1307 break;
1308 case 0x6:
87e92502 1309 gen_op_eval_fbg(r_dst, cpu_fsr, offset);
19f329ad
BS
1310 break;
1311 case 0x7:
87e92502 1312 gen_op_eval_fbu(r_dst, cpu_fsr, offset);
19f329ad
BS
1313 break;
1314 case 0x8:
1315 gen_op_eval_ba(r_dst);
1316 break;
1317 case 0x9:
87e92502 1318 gen_op_eval_fbe(r_dst, cpu_fsr, offset);
19f329ad
BS
1319 break;
1320 case 0xa:
87e92502 1321 gen_op_eval_fbue(r_dst, cpu_fsr, offset);
19f329ad
BS
1322 break;
1323 case 0xb:
87e92502 1324 gen_op_eval_fbge(r_dst, cpu_fsr, offset);
19f329ad
BS
1325 break;
1326 case 0xc:
87e92502 1327 gen_op_eval_fbuge(r_dst, cpu_fsr, offset);
19f329ad
BS
1328 break;
1329 case 0xd:
87e92502 1330 gen_op_eval_fble(r_dst, cpu_fsr, offset);
19f329ad
BS
1331 break;
1332 case 0xe:
87e92502 1333 gen_op_eval_fbule(r_dst, cpu_fsr, offset);
19f329ad
BS
1334 break;
1335 case 0xf:
87e92502 1336 gen_op_eval_fbo(r_dst, cpu_fsr, offset);
19f329ad
BS
1337 break;
1338 }
e8af50a3 1339}
00f219bf 1340
416fcaea
RH
1341static void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
1342 DisasContext *dc)
1343{
1344 DisasCompare cmp;
1345 gen_compare(&cmp, cc, cond, dc);
1346
1347 /* The interface is to return a boolean in r_dst. */
1348 if (cmp.is_bool) {
1349 tcg_gen_mov_tl(r_dst, cmp.c1);
1350 } else {
1351 tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
1352 }
1353
1354 free_compare(&cmp);
1355}
1356
1357static void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
1358{
1359 DisasCompare cmp;
1360 gen_fcompare(&cmp, cc, cond);
1361
1362 /* The interface is to return a boolean in r_dst. */
1363 if (cmp.is_bool) {
1364 tcg_gen_mov_tl(r_dst, cmp.c1);
1365 } else {
1366 tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
1367 }
1368
1369 free_compare(&cmp);
1370}
1371
19f329ad 1372#ifdef TARGET_SPARC64
00f219bf
BS
1373// Inverted logic
1374static const int gen_tcg_cond_reg[8] = {
1375 -1,
1376 TCG_COND_NE,
1377 TCG_COND_GT,
1378 TCG_COND_GE,
1379 -1,
1380 TCG_COND_EQ,
1381 TCG_COND_LE,
1382 TCG_COND_LT,
1383};
19f329ad 1384
416fcaea
RH
1385static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
1386{
1387 cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]);
1388 cmp->is_bool = false;
1389 cmp->g1 = true;
1390 cmp->g2 = false;
1391 cmp->c1 = r_src;
1392 cmp->c2 = tcg_const_tl(0);
1393}
1394
4af984a7 1395static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
19f329ad 1396{
416fcaea
RH
1397 DisasCompare cmp;
1398 gen_compare_reg(&cmp, cond, r_src);
19f329ad 1399
416fcaea
RH
1400 /* The interface is to return a boolean in r_dst. */
1401 tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
1402
1403 free_compare(&cmp);
19f329ad 1404}
3475187d 1405#endif
cf495bcf 1406
d4a288ef 1407static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
7a3f1944 1408{
cf495bcf 1409 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
af7bf89b 1410 target_ulong target = dc->pc + offset;
5fafdf24 1411
22036a49
AT
1412#ifdef TARGET_SPARC64
1413 if (unlikely(AM_CHECK(dc))) {
1414 target &= 0xffffffffULL;
1415 }
1416#endif
cf495bcf 1417 if (cond == 0x0) {
0f8a249a
BS
1418 /* unconditional not taken */
1419 if (a) {
1420 dc->pc = dc->npc + 4;
1421 dc->npc = dc->pc + 4;
1422 } else {
1423 dc->pc = dc->npc;
1424 dc->npc = dc->pc + 4;
1425 }
cf495bcf 1426 } else if (cond == 0x8) {
0f8a249a
BS
1427 /* unconditional taken */
1428 if (a) {
1429 dc->pc = target;
1430 dc->npc = dc->pc + 4;
1431 } else {
1432 dc->pc = dc->npc;
1433 dc->npc = target;
c27e2752 1434 tcg_gen_mov_tl(cpu_pc, cpu_npc);
0f8a249a 1435 }
cf495bcf 1436 } else {
dee8913c 1437 flush_cond(dc);
d4a288ef 1438 gen_cond(cpu_cond, cc, cond, dc);
0f8a249a 1439 if (a) {
bfa31b76 1440 gen_branch_a(dc, target);
0f8a249a 1441 } else {
2bf2e019 1442 gen_branch_n(dc, target);
0f8a249a 1443 }
cf495bcf 1444 }
7a3f1944
FB
1445}
1446
d4a288ef 1447static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
e8af50a3
FB
1448{
1449 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
af7bf89b
FB
1450 target_ulong target = dc->pc + offset;
1451
22036a49
AT
1452#ifdef TARGET_SPARC64
1453 if (unlikely(AM_CHECK(dc))) {
1454 target &= 0xffffffffULL;
1455 }
1456#endif
e8af50a3 1457 if (cond == 0x0) {
0f8a249a
BS
1458 /* unconditional not taken */
1459 if (a) {
1460 dc->pc = dc->npc + 4;
1461 dc->npc = dc->pc + 4;
1462 } else {
1463 dc->pc = dc->npc;
1464 dc->npc = dc->pc + 4;
1465 }
e8af50a3 1466 } else if (cond == 0x8) {
0f8a249a
BS
1467 /* unconditional taken */
1468 if (a) {
1469 dc->pc = target;
1470 dc->npc = dc->pc + 4;
1471 } else {
1472 dc->pc = dc->npc;
1473 dc->npc = target;
c27e2752 1474 tcg_gen_mov_tl(cpu_pc, cpu_npc);
0f8a249a 1475 }
e8af50a3 1476 } else {
dee8913c 1477 flush_cond(dc);
d4a288ef 1478 gen_fcond(cpu_cond, cc, cond);
0f8a249a 1479 if (a) {
bfa31b76 1480 gen_branch_a(dc, target);
0f8a249a 1481 } else {
2bf2e019 1482 gen_branch_n(dc, target);
0f8a249a 1483 }
e8af50a3
FB
1484 }
1485}
1486
3475187d 1487#ifdef TARGET_SPARC64
4af984a7 1488static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
d4a288ef 1489 TCGv r_reg)
7a3f1944 1490{
3475187d
FB
1491 unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
1492 target_ulong target = dc->pc + offset;
1493
22036a49
AT
1494 if (unlikely(AM_CHECK(dc))) {
1495 target &= 0xffffffffULL;
1496 }
dee8913c 1497 flush_cond(dc);
d4a288ef 1498 gen_cond_reg(cpu_cond, cond, r_reg);
3475187d 1499 if (a) {
bfa31b76 1500 gen_branch_a(dc, target);
3475187d 1501 } else {
2bf2e019 1502 gen_branch_n(dc, target);
3475187d 1503 }
7a3f1944
FB
1504}
1505
a7812ae4 1506static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
7e8c2b6c 1507{
714547bb
BS
1508 switch (fccno) {
1509 case 0:
2e2f4ade 1510 gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
714547bb
BS
1511 break;
1512 case 1:
2e2f4ade 1513 gen_helper_fcmps_fcc1(cpu_env, r_rs1, r_rs2);
714547bb
BS
1514 break;
1515 case 2:
2e2f4ade 1516 gen_helper_fcmps_fcc2(cpu_env, r_rs1, r_rs2);
714547bb
BS
1517 break;
1518 case 3:
2e2f4ade 1519 gen_helper_fcmps_fcc3(cpu_env, r_rs1, r_rs2);
714547bb
BS
1520 break;
1521 }
7e8c2b6c
BS
1522}
1523
03fb8cfc 1524static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1525{
a7812ae4
PB
1526 switch (fccno) {
1527 case 0:
03fb8cfc 1528 gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1529 break;
1530 case 1:
03fb8cfc 1531 gen_helper_fcmpd_fcc1(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1532 break;
1533 case 2:
03fb8cfc 1534 gen_helper_fcmpd_fcc2(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1535 break;
1536 case 3:
03fb8cfc 1537 gen_helper_fcmpd_fcc3(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1538 break;
1539 }
7e8c2b6c
BS
1540}
1541
7e8c2b6c
BS
1542static inline void gen_op_fcmpq(int fccno)
1543{
a7812ae4
PB
1544 switch (fccno) {
1545 case 0:
2e2f4ade 1546 gen_helper_fcmpq(cpu_env);
a7812ae4
PB
1547 break;
1548 case 1:
2e2f4ade 1549 gen_helper_fcmpq_fcc1(cpu_env);
a7812ae4
PB
1550 break;
1551 case 2:
2e2f4ade 1552 gen_helper_fcmpq_fcc2(cpu_env);
a7812ae4
PB
1553 break;
1554 case 3:
2e2f4ade 1555 gen_helper_fcmpq_fcc3(cpu_env);
a7812ae4
PB
1556 break;
1557 }
7e8c2b6c 1558}
7e8c2b6c 1559
a7812ae4 1560static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
7e8c2b6c 1561{
714547bb
BS
1562 switch (fccno) {
1563 case 0:
2e2f4ade 1564 gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
714547bb
BS
1565 break;
1566 case 1:
2e2f4ade 1567 gen_helper_fcmpes_fcc1(cpu_env, r_rs1, r_rs2);
714547bb
BS
1568 break;
1569 case 2:
2e2f4ade 1570 gen_helper_fcmpes_fcc2(cpu_env, r_rs1, r_rs2);
714547bb
BS
1571 break;
1572 case 3:
2e2f4ade 1573 gen_helper_fcmpes_fcc3(cpu_env, r_rs1, r_rs2);
714547bb
BS
1574 break;
1575 }
7e8c2b6c
BS
1576}
1577
03fb8cfc 1578static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1579{
a7812ae4
PB
1580 switch (fccno) {
1581 case 0:
03fb8cfc 1582 gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1583 break;
1584 case 1:
03fb8cfc 1585 gen_helper_fcmped_fcc1(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1586 break;
1587 case 2:
03fb8cfc 1588 gen_helper_fcmped_fcc2(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1589 break;
1590 case 3:
03fb8cfc 1591 gen_helper_fcmped_fcc3(cpu_env, r_rs1, r_rs2);
a7812ae4
PB
1592 break;
1593 }
7e8c2b6c
BS
1594}
1595
7e8c2b6c
BS
1596static inline void gen_op_fcmpeq(int fccno)
1597{
a7812ae4
PB
1598 switch (fccno) {
1599 case 0:
2e2f4ade 1600 gen_helper_fcmpeq(cpu_env);
a7812ae4
PB
1601 break;
1602 case 1:
2e2f4ade 1603 gen_helper_fcmpeq_fcc1(cpu_env);
a7812ae4
PB
1604 break;
1605 case 2:
2e2f4ade 1606 gen_helper_fcmpeq_fcc2(cpu_env);
a7812ae4
PB
1607 break;
1608 case 3:
2e2f4ade 1609 gen_helper_fcmpeq_fcc3(cpu_env);
a7812ae4
PB
1610 break;
1611 }
7e8c2b6c 1612}
7e8c2b6c
BS
1613
1614#else
1615
714547bb 1616static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
7e8c2b6c 1617{
2e2f4ade 1618 gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
7e8c2b6c
BS
1619}
1620
03fb8cfc 1621static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1622{
03fb8cfc 1623 gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
7e8c2b6c
BS
1624}
1625
7e8c2b6c
BS
1626static inline void gen_op_fcmpq(int fccno)
1627{
2e2f4ade 1628 gen_helper_fcmpq(cpu_env);
7e8c2b6c 1629}
7e8c2b6c 1630
714547bb 1631static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
7e8c2b6c 1632{
2e2f4ade 1633 gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
7e8c2b6c
BS
1634}
1635
03fb8cfc 1636static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1637{
03fb8cfc 1638 gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
7e8c2b6c
BS
1639}
1640
7e8c2b6c
BS
1641static inline void gen_op_fcmpeq(int fccno)
1642{
2e2f4ade 1643 gen_helper_fcmpeq(cpu_env);
7e8c2b6c
BS
1644}
1645#endif
1646
4fbe0067 1647static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags)
134d77a1 1648{
47ad35f1 1649 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
87e92502 1650 tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
4fbe0067 1651 gen_exception(dc, TT_FP_EXCP);
134d77a1
BS
1652}
1653
5b12f1e8 1654static int gen_trap_ifnofpu(DisasContext *dc)
a80dde08
FB
1655{
1656#if !defined(CONFIG_USER_ONLY)
1657 if (!dc->fpu_enabled) {
4fbe0067 1658 gen_exception(dc, TT_NFPU_INSN);
a80dde08
FB
1659 return 1;
1660 }
1661#endif
1662 return 0;
1663}
1664
7e8c2b6c
BS
1665static inline void gen_op_clear_ieee_excp_and_FTT(void)
1666{
47ad35f1 1667 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
7e8c2b6c
BS
1668}
1669
61f17f6e
RH
1670static inline void gen_fop_FF(DisasContext *dc, int rd, int rs,
1671 void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32))
1672{
1673 TCGv_i32 dst, src;
1674
61f17f6e 1675 src = gen_load_fpr_F(dc, rs);
ba5f5179 1676 dst = gen_dest_fpr_F(dc);
61f17f6e
RH
1677
1678 gen(dst, cpu_env, src);
1679
61f17f6e
RH
1680 gen_store_fpr_F(dc, rd, dst);
1681}
1682
1683static inline void gen_ne_fop_FF(DisasContext *dc, int rd, int rs,
1684 void (*gen)(TCGv_i32, TCGv_i32))
1685{
1686 TCGv_i32 dst, src;
1687
1688 src = gen_load_fpr_F(dc, rs);
ba5f5179 1689 dst = gen_dest_fpr_F(dc);
61f17f6e
RH
1690
1691 gen(dst, src);
1692
1693 gen_store_fpr_F(dc, rd, dst);
1694}
1695
1696static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
1697 void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32))
1698{
1699 TCGv_i32 dst, src1, src2;
1700
61f17f6e
RH
1701 src1 = gen_load_fpr_F(dc, rs1);
1702 src2 = gen_load_fpr_F(dc, rs2);
ba5f5179 1703 dst = gen_dest_fpr_F(dc);
61f17f6e
RH
1704
1705 gen(dst, cpu_env, src1, src2);
1706
61f17f6e
RH
1707 gen_store_fpr_F(dc, rd, dst);
1708}
1709
1710#ifdef TARGET_SPARC64
1711static inline void gen_ne_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
1712 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
1713{
1714 TCGv_i32 dst, src1, src2;
1715
1716 src1 = gen_load_fpr_F(dc, rs1);
1717 src2 = gen_load_fpr_F(dc, rs2);
ba5f5179 1718 dst = gen_dest_fpr_F(dc);
61f17f6e
RH
1719
1720 gen(dst, src1, src2);
1721
1722 gen_store_fpr_F(dc, rd, dst);
1723}
1724#endif
1725
1726static inline void gen_fop_DD(DisasContext *dc, int rd, int rs,
1727 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64))
1728{
1729 TCGv_i64 dst, src;
1730
61f17f6e 1731 src = gen_load_fpr_D(dc, rs);
3886b8a3 1732 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1733
1734 gen(dst, cpu_env, src);
1735
61f17f6e
RH
1736 gen_store_fpr_D(dc, rd, dst);
1737}
1738
1739#ifdef TARGET_SPARC64
1740static inline void gen_ne_fop_DD(DisasContext *dc, int rd, int rs,
1741 void (*gen)(TCGv_i64, TCGv_i64))
1742{
1743 TCGv_i64 dst, src;
1744
1745 src = gen_load_fpr_D(dc, rs);
3886b8a3 1746 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1747
1748 gen(dst, src);
1749
1750 gen_store_fpr_D(dc, rd, dst);
1751}
1752#endif
1753
1754static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1755 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64))
1756{
1757 TCGv_i64 dst, src1, src2;
1758
61f17f6e
RH
1759 src1 = gen_load_fpr_D(dc, rs1);
1760 src2 = gen_load_fpr_D(dc, rs2);
3886b8a3 1761 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1762
1763 gen(dst, cpu_env, src1, src2);
1764
61f17f6e
RH
1765 gen_store_fpr_D(dc, rd, dst);
1766}
1767
1768#ifdef TARGET_SPARC64
1769static inline void gen_ne_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1770 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
1771{
1772 TCGv_i64 dst, src1, src2;
1773
1774 src1 = gen_load_fpr_D(dc, rs1);
1775 src2 = gen_load_fpr_D(dc, rs2);
3886b8a3 1776 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1777
1778 gen(dst, src1, src2);
1779
1780 gen_store_fpr_D(dc, rd, dst);
1781}
f888300b 1782
2dedf314
RH
1783static inline void gen_gsr_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1784 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
1785{
1786 TCGv_i64 dst, src1, src2;
1787
1788 src1 = gen_load_fpr_D(dc, rs1);
1789 src2 = gen_load_fpr_D(dc, rs2);
3886b8a3 1790 dst = gen_dest_fpr_D(dc, rd);
2dedf314
RH
1791
1792 gen(dst, cpu_gsr, src1, src2);
1793
1794 gen_store_fpr_D(dc, rd, dst);
1795}
1796
f888300b
RH
1797static inline void gen_ne_fop_DDDD(DisasContext *dc, int rd, int rs1, int rs2,
1798 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
1799{
1800 TCGv_i64 dst, src0, src1, src2;
1801
1802 src1 = gen_load_fpr_D(dc, rs1);
1803 src2 = gen_load_fpr_D(dc, rs2);
1804 src0 = gen_load_fpr_D(dc, rd);
3886b8a3 1805 dst = gen_dest_fpr_D(dc, rd);
f888300b
RH
1806
1807 gen(dst, src0, src1, src2);
1808
1809 gen_store_fpr_D(dc, rd, dst);
1810}
61f17f6e
RH
1811#endif
1812
1813static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs,
1814 void (*gen)(TCGv_ptr))
1815{
61f17f6e
RH
1816 gen_op_load_fpr_QT1(QFPREG(rs));
1817
1818 gen(cpu_env);
1819
61f17f6e
RH
1820 gen_op_store_QT0_fpr(QFPREG(rd));
1821 gen_update_fprs_dirty(QFPREG(rd));
1822}
1823
1824#ifdef TARGET_SPARC64
1825static inline void gen_ne_fop_QQ(DisasContext *dc, int rd, int rs,
1826 void (*gen)(TCGv_ptr))
1827{
1828 gen_op_load_fpr_QT1(QFPREG(rs));
1829
1830 gen(cpu_env);
1831
1832 gen_op_store_QT0_fpr(QFPREG(rd));
1833 gen_update_fprs_dirty(QFPREG(rd));
1834}
1835#endif
1836
1837static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2,
1838 void (*gen)(TCGv_ptr))
1839{
61f17f6e
RH
1840 gen_op_load_fpr_QT0(QFPREG(rs1));
1841 gen_op_load_fpr_QT1(QFPREG(rs2));
1842
1843 gen(cpu_env);
1844
61f17f6e
RH
1845 gen_op_store_QT0_fpr(QFPREG(rd));
1846 gen_update_fprs_dirty(QFPREG(rd));
1847}
1848
1849static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2,
1850 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32, TCGv_i32))
1851{
1852 TCGv_i64 dst;
1853 TCGv_i32 src1, src2;
1854
61f17f6e
RH
1855 src1 = gen_load_fpr_F(dc, rs1);
1856 src2 = gen_load_fpr_F(dc, rs2);
3886b8a3 1857 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1858
1859 gen(dst, cpu_env, src1, src2);
1860
61f17f6e
RH
1861 gen_store_fpr_D(dc, rd, dst);
1862}
1863
1864static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2,
1865 void (*gen)(TCGv_ptr, TCGv_i64, TCGv_i64))
1866{
1867 TCGv_i64 src1, src2;
1868
61f17f6e
RH
1869 src1 = gen_load_fpr_D(dc, rs1);
1870 src2 = gen_load_fpr_D(dc, rs2);
1871
1872 gen(cpu_env, src1, src2);
1873
61f17f6e
RH
1874 gen_op_store_QT0_fpr(QFPREG(rd));
1875 gen_update_fprs_dirty(QFPREG(rd));
1876}
1877
1878#ifdef TARGET_SPARC64
1879static inline void gen_fop_DF(DisasContext *dc, int rd, int rs,
1880 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
1881{
1882 TCGv_i64 dst;
1883 TCGv_i32 src;
1884
61f17f6e 1885 src = gen_load_fpr_F(dc, rs);
3886b8a3 1886 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1887
1888 gen(dst, cpu_env, src);
1889
61f17f6e
RH
1890 gen_store_fpr_D(dc, rd, dst);
1891}
1892#endif
1893
1894static inline void gen_ne_fop_DF(DisasContext *dc, int rd, int rs,
1895 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
1896{
1897 TCGv_i64 dst;
1898 TCGv_i32 src;
1899
1900 src = gen_load_fpr_F(dc, rs);
3886b8a3 1901 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1902
1903 gen(dst, cpu_env, src);
1904
1905 gen_store_fpr_D(dc, rd, dst);
1906}
1907
1908static inline void gen_fop_FD(DisasContext *dc, int rd, int rs,
1909 void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i64))
1910{
1911 TCGv_i32 dst;
1912 TCGv_i64 src;
1913
61f17f6e 1914 src = gen_load_fpr_D(dc, rs);
ba5f5179 1915 dst = gen_dest_fpr_F(dc);
61f17f6e
RH
1916
1917 gen(dst, cpu_env, src);
1918
61f17f6e
RH
1919 gen_store_fpr_F(dc, rd, dst);
1920}
1921
1922static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs,
1923 void (*gen)(TCGv_i32, TCGv_ptr))
1924{
1925 TCGv_i32 dst;
1926
61f17f6e 1927 gen_op_load_fpr_QT1(QFPREG(rs));
ba5f5179 1928 dst = gen_dest_fpr_F(dc);
61f17f6e
RH
1929
1930 gen(dst, cpu_env);
1931
61f17f6e
RH
1932 gen_store_fpr_F(dc, rd, dst);
1933}
1934
1935static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs,
1936 void (*gen)(TCGv_i64, TCGv_ptr))
1937{
1938 TCGv_i64 dst;
1939
61f17f6e 1940 gen_op_load_fpr_QT1(QFPREG(rs));
3886b8a3 1941 dst = gen_dest_fpr_D(dc, rd);
61f17f6e
RH
1942
1943 gen(dst, cpu_env);
1944
61f17f6e
RH
1945 gen_store_fpr_D(dc, rd, dst);
1946}
1947
1948static inline void gen_ne_fop_QF(DisasContext *dc, int rd, int rs,
1949 void (*gen)(TCGv_ptr, TCGv_i32))
1950{
1951 TCGv_i32 src;
1952
1953 src = gen_load_fpr_F(dc, rs);
1954
1955 gen(cpu_env, src);
1956
1957 gen_op_store_QT0_fpr(QFPREG(rd));
1958 gen_update_fprs_dirty(QFPREG(rd));
1959}
1960
1961static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
1962 void (*gen)(TCGv_ptr, TCGv_i64))
1963{
1964 TCGv_i64 src;
1965
1966 src = gen_load_fpr_D(dc, rs);
1967
1968 gen(cpu_env, src);
1969
1970 gen_op_store_QT0_fpr(QFPREG(rd));
1971 gen_update_fprs_dirty(QFPREG(rd));
1972}
1973
1a2fb1c0 1974/* asi moves */
22e70060
RH
1975#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1976static TCGv_i32 gen_get_asi(DisasContext *dc, int insn)
1a2fb1c0 1977{
22e70060 1978 TCGv_i32 r_asi = tcg_temp_new_i32();
1a2fb1c0 1979
1a2fb1c0 1980 if (IS_IMM) {
22e70060 1981#ifdef TARGET_SPARC64
255e1fcb 1982 tcg_gen_mov_i32(r_asi, cpu_asi);
22e70060
RH
1983#else
1984 gen_exception(dc, TT_ILL_INSN);
1985 tcg_gen_movi_i32(r_asi, 0);
1986#endif
1a2fb1c0 1987 } else {
22e70060 1988 tcg_gen_movi_i32(r_asi, GET_FIELD(insn, 19, 26));
1a2fb1c0 1989 }
0425bee5
BS
1990 return r_asi;
1991}
1992
22e70060
RH
1993static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
1994 int insn, int size, int sign)
0425bee5 1995{
a7812ae4 1996 TCGv_i32 r_asi, r_size, r_sign;
0425bee5 1997
22e70060 1998 r_asi = gen_get_asi(dc, insn);
2ea815ca
BS
1999 r_size = tcg_const_i32(size);
2000 r_sign = tcg_const_i32(sign);
22e70060 2001#ifdef TARGET_SPARC64
fe8d8f0f 2002 gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
22e70060
RH
2003#else
2004 {
2005 TCGv_i64 t64 = tcg_temp_new_i64();
2006 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
2007 tcg_gen_trunc_i64_tl(dst, t64);
2008 tcg_temp_free_i64(t64);
2009 }
2010#endif
a7812ae4
PB
2011 tcg_temp_free_i32(r_sign);
2012 tcg_temp_free_i32(r_size);
2013 tcg_temp_free_i32(r_asi);
1a2fb1c0
BS
2014}
2015
22e70060
RH
2016static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
2017 int insn, int size)
1a2fb1c0 2018{
a7812ae4 2019 TCGv_i32 r_asi, r_size;
1a2fb1c0 2020
22e70060 2021 r_asi = gen_get_asi(dc, insn);
2ea815ca 2022 r_size = tcg_const_i32(size);
22e70060 2023#ifdef TARGET_SPARC64
fe8d8f0f 2024 gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
22e70060
RH
2025#else
2026 {
2027 TCGv_i64 t64 = tcg_temp_new_i64();
2028 tcg_gen_extu_tl_i64(t64, src);
2029 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
2030 tcg_temp_free_i64(t64);
2031 }
2032#endif
a7812ae4
PB
2033 tcg_temp_free_i32(r_size);
2034 tcg_temp_free_i32(r_asi);
1a2fb1c0
BS
2035}
2036
22e70060
RH
2037static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
2038 TCGv addr, int insn)
1a2fb1c0 2039{
22e70060
RH
2040 TCGv_i32 r_asi, r_size, r_sign;
2041 TCGv_i64 s64, t64 = tcg_temp_new_i64();
1a2fb1c0 2042
22e70060
RH
2043 r_asi = gen_get_asi(dc, insn);
2044 r_size = tcg_const_i32(4);
2045 r_sign = tcg_const_i32(0);
2046 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
2047 tcg_temp_free_i32(r_sign);
2048
2049 s64 = tcg_temp_new_i64();
2050 tcg_gen_extu_tl_i64(s64, src);
2051 gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
2052 tcg_temp_free_i64(s64);
a7812ae4
PB
2053 tcg_temp_free_i32(r_size);
2054 tcg_temp_free_i32(r_asi);
22e70060
RH
2055
2056 tcg_gen_trunc_i64_tl(dst, t64);
2057 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2058}
2059
22e70060
RH
2060static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
2061 int insn, int rd)
2062{
2063 TCGv val1 = gen_load_gpr(dc, rd);
2064 TCGv dst = gen_dest_gpr(dc, rd);
2065 TCGv_i32 r_asi = gen_get_asi(dc, insn);
2066
2067 gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
2068 tcg_temp_free_i32(r_asi);
2069 gen_store_gpr(dc, rd, dst);
2070}
2071
2072static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
2073{
2074 TCGv_i32 r_asi, r_size, r_sign;
2075 TCGv_i64 s64, d64 = tcg_temp_new_i64();
2076
2077 r_asi = gen_get_asi(dc, insn);
2078 r_size = tcg_const_i32(1);
2079 r_sign = tcg_const_i32(0);
2080 gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_size, r_sign);
2081 tcg_temp_free_i32(r_sign);
2082
2083 s64 = tcg_const_i64(0xff);
2084 gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
2085 tcg_temp_free_i64(s64);
2086 tcg_temp_free_i32(r_size);
2087 tcg_temp_free_i32(r_asi);
2088
2089 tcg_gen_trunc_i64_tl(dst, d64);
2090 tcg_temp_free_i64(d64);
2091}
2092#endif
2093
2094#ifdef TARGET_SPARC64
2095static void gen_ldf_asi(DisasContext *dc, TCGv addr,
2096 int insn, int size, int rd)
1a2fb1c0 2097{
a7812ae4 2098 TCGv_i32 r_asi, r_size, r_rd;
1a2fb1c0 2099
22e70060 2100 r_asi = gen_get_asi(dc, insn);
2ea815ca
BS
2101 r_size = tcg_const_i32(size);
2102 r_rd = tcg_const_i32(rd);
22e70060 2103 gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
a7812ae4
PB
2104 tcg_temp_free_i32(r_rd);
2105 tcg_temp_free_i32(r_size);
2106 tcg_temp_free_i32(r_asi);
1a2fb1c0
BS
2107}
2108
22e70060
RH
2109static void gen_stf_asi(DisasContext *dc, TCGv addr,
2110 int insn, int size, int rd)
1a2fb1c0 2111{
22e70060 2112 TCGv_i32 r_asi, r_size, r_rd;
1a2fb1c0 2113
22e70060
RH
2114 r_asi = gen_get_asi(dc, insn);
2115 r_size = tcg_const_i32(size);
2116 r_rd = tcg_const_i32(rd);
2117 gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
2118 tcg_temp_free_i32(r_rd);
a7812ae4
PB
2119 tcg_temp_free_i32(r_size);
2120 tcg_temp_free_i32(r_asi);
1a2fb1c0
BS
2121}
2122
22e70060
RH
2123static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2124 int insn, int rd)
1a2fb1c0 2125{
a7812ae4 2126 TCGv_i32 r_asi, r_rd;
1a2fb1c0 2127
22e70060 2128 r_asi = gen_get_asi(dc, insn);
db166940 2129 r_rd = tcg_const_i32(rd);
fe8d8f0f 2130 gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
a7812ae4
PB
2131 tcg_temp_free_i32(r_rd);
2132 tcg_temp_free_i32(r_asi);
0425bee5
BS
2133}
2134
22e70060
RH
2135static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2136 int insn, int rd)
0425bee5 2137{
a7812ae4 2138 TCGv_i32 r_asi, r_size;
c7785e16 2139 TCGv lo = gen_load_gpr(dc, rd + 1);
1ec789ab 2140 TCGv_i64 t64 = tcg_temp_new_i64();
a7ec4229 2141
1ec789ab 2142 tcg_gen_concat_tl_i64(t64, lo, hi);
22e70060 2143 r_asi = gen_get_asi(dc, insn);
2ea815ca 2144 r_size = tcg_const_i32(8);
1ec789ab 2145 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
a7812ae4
PB
2146 tcg_temp_free_i32(r_size);
2147 tcg_temp_free_i32(r_asi);
1ec789ab 2148 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2149}
2150
22e70060
RH
2151static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
2152 int insn, int rd)
1a2fb1c0 2153{
81634eea
RH
2154 TCGv val1 = gen_load_gpr(dc, rd);
2155 TCGv dst = gen_dest_gpr(dc, rd);
22e70060 2156 TCGv_i32 r_asi = gen_get_asi(dc, insn);
1a2fb1c0 2157
81634eea 2158 gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi);
a7812ae4 2159 tcg_temp_free_i32(r_asi);
81634eea 2160 gen_store_gpr(dc, rd, dst);
1a2fb1c0
BS
2161}
2162
2163#elif !defined(CONFIG_USER_ONLY)
22e70060
RH
2164static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2165 int insn, int rd)
1a2fb1c0 2166{
a7812ae4 2167 TCGv_i32 r_asi, r_size, r_sign;
c7785e16 2168 TCGv t;
1ec789ab 2169 TCGv_i64 t64;
1a2fb1c0 2170
22e70060 2171 r_asi = gen_get_asi(dc, insn);
2ea815ca
BS
2172 r_size = tcg_const_i32(8);
2173 r_sign = tcg_const_i32(0);
1ec789ab
RH
2174 t64 = tcg_temp_new_i64();
2175 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
2176 tcg_temp_free_i32(r_sign);
2177 tcg_temp_free_i32(r_size);
2178 tcg_temp_free_i32(r_asi);
c7785e16 2179
d2dc4069
RH
2180 /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
2181 whereby "rd + 1" elicits "error: array subscript is above array".
2182 Since we have already asserted that rd is even, the semantics
2183 are unchanged. */
2184 t = gen_dest_gpr(dc, rd | 1);
1ec789ab 2185 tcg_gen_trunc_i64_tl(t, t64);
d2dc4069 2186 gen_store_gpr(dc, rd | 1, t);
c7785e16 2187
1ec789ab
RH
2188 tcg_gen_shri_i64(t64, t64, 32);
2189 tcg_gen_trunc_i64_tl(hi, t64);
2190 tcg_temp_free_i64(t64);
c7785e16 2191 gen_store_gpr(dc, rd, hi);
0425bee5
BS
2192}
2193
22e70060
RH
2194static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2195 int insn, int rd)
0425bee5 2196{
a7812ae4 2197 TCGv_i32 r_asi, r_size;
c7785e16 2198 TCGv lo = gen_load_gpr(dc, rd + 1);
1ec789ab 2199 TCGv_i64 t64 = tcg_temp_new_i64();
a7ec4229 2200
1ec789ab 2201 tcg_gen_concat_tl_i64(t64, lo, hi);
22e70060 2202 r_asi = gen_get_asi(dc, insn);
2ea815ca 2203 r_size = tcg_const_i32(8);
1ec789ab
RH
2204 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
2205 tcg_temp_free_i32(r_size);
2206 tcg_temp_free_i32(r_asi);
2207 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2208}
2209#endif
2210
9d1d4e34 2211static TCGv get_src1(DisasContext *dc, unsigned int insn)
9322a4bf 2212{
9d1d4e34
RH
2213 unsigned int rs1 = GET_FIELD(insn, 13, 17);
2214 return gen_load_gpr(dc, rs1);
9322a4bf
BS
2215}
2216
9d1d4e34 2217static TCGv get_src2(DisasContext *dc, unsigned int insn)
a49d9390 2218{
a49d9390 2219 if (IS_IMM) { /* immediate */
42a8aa83 2220 target_long simm = GET_FIELDs(insn, 19, 31);
9d1d4e34
RH
2221 TCGv t = get_temp_tl(dc);
2222 tcg_gen_movi_tl(t, simm);
2223 return t;
2224 } else { /* register */
42a8aa83 2225 unsigned int rs2 = GET_FIELD(insn, 27, 31);
9d1d4e34 2226 return gen_load_gpr(dc, rs2);
a49d9390 2227 }
a49d9390
BS
2228}
2229
8194f35a 2230#ifdef TARGET_SPARC64
7e480893
RH
2231static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2232{
2233 TCGv_i32 c32, zero, dst, s1, s2;
2234
2235 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2236 or fold the comparison down to 32 bits and use movcond_i32. Choose
2237 the later. */
2238 c32 = tcg_temp_new_i32();
2239 if (cmp->is_bool) {
ecc7b3aa 2240 tcg_gen_extrl_i64_i32(c32, cmp->c1);
7e480893
RH
2241 } else {
2242 TCGv_i64 c64 = tcg_temp_new_i64();
2243 tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
ecc7b3aa 2244 tcg_gen_extrl_i64_i32(c32, c64);
7e480893
RH
2245 tcg_temp_free_i64(c64);
2246 }
2247
2248 s1 = gen_load_fpr_F(dc, rs);
2249 s2 = gen_load_fpr_F(dc, rd);
ba5f5179 2250 dst = gen_dest_fpr_F(dc);
7e480893
RH
2251 zero = tcg_const_i32(0);
2252
2253 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2254
2255 tcg_temp_free_i32(c32);
2256 tcg_temp_free_i32(zero);
2257 gen_store_fpr_F(dc, rd, dst);
2258}
2259
2260static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2261{
3886b8a3 2262 TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
7e480893
RH
2263 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
2264 gen_load_fpr_D(dc, rs),
2265 gen_load_fpr_D(dc, rd));
2266 gen_store_fpr_D(dc, rd, dst);
2267}
2268
2269static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2270{
2271 int qd = QFPREG(rd);
2272 int qs = QFPREG(rs);
2273
2274 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
2275 cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2276 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
2277 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2278
2279 gen_update_fprs_dirty(qd);
2280}
2281
a2035e83 2282#ifndef CONFIG_USER_ONLY
1bcea73e 2283static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env cpu_env)
8194f35a 2284{
b551ec04 2285 TCGv_i32 r_tl = tcg_temp_new_i32();
8194f35a
IK
2286
2287 /* load env->tl into r_tl */
b551ec04 2288 tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
8194f35a
IK
2289
2290 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
b551ec04 2291 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
8194f35a
IK
2292
2293 /* calculate offset to current trap state from env->ts, reuse r_tl */
b551ec04 2294 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
c5f9864e 2295 tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts));
8194f35a
IK
2296
2297 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
b551ec04
JF
2298 {
2299 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2300 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2301 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
bc57c114 2302 tcg_temp_free_ptr(r_tl_tmp);
b551ec04 2303 }
8194f35a 2304
b551ec04 2305 tcg_temp_free_i32(r_tl);
8194f35a 2306}
a2035e83 2307#endif
6c073553
RH
2308
2309static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
2310 int width, bool cc, bool left)
2311{
2312 TCGv lo1, lo2, t1, t2;
2313 uint64_t amask, tabl, tabr;
2314 int shift, imask, omask;
2315
2316 if (cc) {
2317 tcg_gen_mov_tl(cpu_cc_src, s1);
2318 tcg_gen_mov_tl(cpu_cc_src2, s2);
2319 tcg_gen_sub_tl(cpu_cc_dst, s1, s2);
2320 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
2321 dc->cc_op = CC_OP_SUB;
2322 }
2323
2324 /* Theory of operation: there are two tables, left and right (not to
2325 be confused with the left and right versions of the opcode). These
2326 are indexed by the low 3 bits of the inputs. To make things "easy",
2327 these tables are loaded into two constants, TABL and TABR below.
2328 The operation index = (input & imask) << shift calculates the index
2329 into the constant, while val = (table >> index) & omask calculates
2330 the value we're looking for. */
2331 switch (width) {
2332 case 8:
2333 imask = 0x7;
2334 shift = 3;
2335 omask = 0xff;
2336 if (left) {
2337 tabl = 0x80c0e0f0f8fcfeffULL;
2338 tabr = 0xff7f3f1f0f070301ULL;
2339 } else {
2340 tabl = 0x0103070f1f3f7fffULL;
2341 tabr = 0xfffefcf8f0e0c080ULL;
2342 }
2343 break;
2344 case 16:
2345 imask = 0x6;
2346 shift = 1;
2347 omask = 0xf;
2348 if (left) {
2349 tabl = 0x8cef;
2350 tabr = 0xf731;
2351 } else {
2352 tabl = 0x137f;
2353 tabr = 0xfec8;
2354 }
2355 break;
2356 case 32:
2357 imask = 0x4;
2358 shift = 0;
2359 omask = 0x3;
2360 if (left) {
2361 tabl = (2 << 2) | 3;
2362 tabr = (3 << 2) | 1;
2363 } else {
2364 tabl = (1 << 2) | 3;
2365 tabr = (3 << 2) | 2;
2366 }
2367 break;
2368 default:
2369 abort();
2370 }
2371
2372 lo1 = tcg_temp_new();
2373 lo2 = tcg_temp_new();
2374 tcg_gen_andi_tl(lo1, s1, imask);
2375 tcg_gen_andi_tl(lo2, s2, imask);
2376 tcg_gen_shli_tl(lo1, lo1, shift);
2377 tcg_gen_shli_tl(lo2, lo2, shift);
2378
2379 t1 = tcg_const_tl(tabl);
2380 t2 = tcg_const_tl(tabr);
2381 tcg_gen_shr_tl(lo1, t1, lo1);
2382 tcg_gen_shr_tl(lo2, t2, lo2);
2383 tcg_gen_andi_tl(dst, lo1, omask);
2384 tcg_gen_andi_tl(lo2, lo2, omask);
2385
2386 amask = -8;
2387 if (AM_CHECK(dc)) {
2388 amask &= 0xffffffffULL;
2389 }
2390 tcg_gen_andi_tl(s1, s1, amask);
2391 tcg_gen_andi_tl(s2, s2, amask);
2392
2393 /* We want to compute
2394 dst = (s1 == s2 ? lo1 : lo1 & lo2).
2395 We've already done dst = lo1, so this reduces to
2396 dst &= (s1 == s2 ? -1 : lo2)
2397 Which we perform by
2398 lo2 |= -(s1 == s2)
2399 dst &= lo2
2400 */
2401 tcg_gen_setcond_tl(TCG_COND_EQ, t1, s1, s2);
2402 tcg_gen_neg_tl(t1, t1);
2403 tcg_gen_or_tl(lo2, lo2, t1);
2404 tcg_gen_and_tl(dst, dst, lo2);
2405
2406 tcg_temp_free(lo1);
2407 tcg_temp_free(lo2);
2408 tcg_temp_free(t1);
2409 tcg_temp_free(t2);
2410}
add545ab
RH
2411
2412static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)
2413{
2414 TCGv tmp = tcg_temp_new();
2415
2416 tcg_gen_add_tl(tmp, s1, s2);
2417 tcg_gen_andi_tl(dst, tmp, -8);
2418 if (left) {
2419 tcg_gen_neg_tl(tmp, tmp);
2420 }
2421 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
2422
2423 tcg_temp_free(tmp);
2424}
50c796f9
RH
2425
2426static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
2427{
2428 TCGv t1, t2, shift;
2429
2430 t1 = tcg_temp_new();
2431 t2 = tcg_temp_new();
2432 shift = tcg_temp_new();
2433
2434 tcg_gen_andi_tl(shift, gsr, 7);
2435 tcg_gen_shli_tl(shift, shift, 3);
2436 tcg_gen_shl_tl(t1, s1, shift);
2437
2438 /* A shift of 64 does not produce 0 in TCG. Divide this into a
2439 shift of (up to 63) followed by a constant shift of 1. */
2440 tcg_gen_xori_tl(shift, shift, 63);
2441 tcg_gen_shr_tl(t2, s2, shift);
2442 tcg_gen_shri_tl(t2, t2, 1);
2443
2444 tcg_gen_or_tl(dst, t1, t2);
2445
2446 tcg_temp_free(t1);
2447 tcg_temp_free(t2);
2448 tcg_temp_free(shift);
2449}
8194f35a
IK
2450#endif
2451
64a88d5d 2452#define CHECK_IU_FEATURE(dc, FEATURE) \
5578ceab 2453 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
2454 goto illegal_insn;
2455#define CHECK_FPU_FEATURE(dc, FEATURE) \
5578ceab 2456 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
2457 goto nfpu_insn;
2458
0bee699e 2459/* before an instruction, dc->pc must be static */
0184e266 2460static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
cf495bcf 2461{
0184e266 2462 unsigned int opc, rs1, rs2, rd;
a4273524 2463 TCGv cpu_src1, cpu_src2;
208ae657 2464 TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
96eda024 2465 TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
67526b20 2466 target_long simm;
7a3f1944 2467
cf495bcf 2468 opc = GET_FIELD(insn, 0, 1);
cf495bcf 2469 rd = GET_FIELD(insn, 2, 6);
6ae20372 2470
cf495bcf 2471 switch (opc) {
0f8a249a
BS
2472 case 0: /* branches/sethi */
2473 {
2474 unsigned int xop = GET_FIELD(insn, 7, 9);
2475 int32_t target;
2476 switch (xop) {
3475187d 2477#ifdef TARGET_SPARC64
0f8a249a
BS
2478 case 0x1: /* V9 BPcc */
2479 {
2480 int cc;
2481
2482 target = GET_FIELD_SP(insn, 0, 18);
86f1f2ae 2483 target = sign_extend(target, 19);
0f8a249a
BS
2484 target <<= 2;
2485 cc = GET_FIELD_SP(insn, 20, 21);
2486 if (cc == 0)
d4a288ef 2487 do_branch(dc, target, insn, 0);
0f8a249a 2488 else if (cc == 2)
d4a288ef 2489 do_branch(dc, target, insn, 1);
0f8a249a
BS
2490 else
2491 goto illegal_insn;
2492 goto jmp_insn;
2493 }
2494 case 0x3: /* V9 BPr */
2495 {
2496 target = GET_FIELD_SP(insn, 0, 13) |
13846e70 2497 (GET_FIELD_SP(insn, 20, 21) << 14);
0f8a249a
BS
2498 target = sign_extend(target, 16);
2499 target <<= 2;
9d1d4e34 2500 cpu_src1 = get_src1(dc, insn);
d4a288ef 2501 do_branch_reg(dc, target, insn, cpu_src1);
0f8a249a
BS
2502 goto jmp_insn;
2503 }
2504 case 0x5: /* V9 FBPcc */
2505 {
2506 int cc = GET_FIELD_SP(insn, 20, 21);
5b12f1e8 2507 if (gen_trap_ifnofpu(dc)) {
a80dde08 2508 goto jmp_insn;
5b12f1e8 2509 }
0f8a249a
BS
2510 target = GET_FIELD_SP(insn, 0, 18);
2511 target = sign_extend(target, 19);
2512 target <<= 2;
d4a288ef 2513 do_fbranch(dc, target, insn, cc);
0f8a249a
BS
2514 goto jmp_insn;
2515 }
a4d17f19 2516#else
0f8a249a
BS
2517 case 0x7: /* CBN+x */
2518 {
2519 goto ncp_insn;
2520 }
2521#endif
2522 case 0x2: /* BN+x */
2523 {
2524 target = GET_FIELD(insn, 10, 31);
2525 target = sign_extend(target, 22);
2526 target <<= 2;
d4a288ef 2527 do_branch(dc, target, insn, 0);
0f8a249a
BS
2528 goto jmp_insn;
2529 }
2530 case 0x6: /* FBN+x */
2531 {
5b12f1e8 2532 if (gen_trap_ifnofpu(dc)) {
a80dde08 2533 goto jmp_insn;
5b12f1e8 2534 }
0f8a249a
BS
2535 target = GET_FIELD(insn, 10, 31);
2536 target = sign_extend(target, 22);
2537 target <<= 2;
d4a288ef 2538 do_fbranch(dc, target, insn, 0);
0f8a249a
BS
2539 goto jmp_insn;
2540 }
2541 case 0x4: /* SETHI */
97ea2859
RH
2542 /* Special-case %g0 because that's the canonical nop. */
2543 if (rd) {
0f8a249a 2544 uint32_t value = GET_FIELD(insn, 10, 31);
97ea2859
RH
2545 TCGv t = gen_dest_gpr(dc, rd);
2546 tcg_gen_movi_tl(t, value << 10);
2547 gen_store_gpr(dc, rd, t);
0f8a249a 2548 }
0f8a249a
BS
2549 break;
2550 case 0x0: /* UNIMPL */
2551 default:
3475187d 2552 goto illegal_insn;
0f8a249a
BS
2553 }
2554 break;
2555 }
2556 break;
dc1a6971
BS
2557 case 1: /*CALL*/
2558 {
0f8a249a 2559 target_long target = GET_FIELDs(insn, 2, 31) << 2;
97ea2859 2560 TCGv o7 = gen_dest_gpr(dc, 15);
cf495bcf 2561
97ea2859
RH
2562 tcg_gen_movi_tl(o7, dc->pc);
2563 gen_store_gpr(dc, 15, o7);
0f8a249a 2564 target += dc->pc;
13a6dd00 2565 gen_mov_pc_npc(dc);
22036a49
AT
2566#ifdef TARGET_SPARC64
2567 if (unlikely(AM_CHECK(dc))) {
2568 target &= 0xffffffffULL;
2569 }
2570#endif
0f8a249a
BS
2571 dc->npc = target;
2572 }
2573 goto jmp_insn;
2574 case 2: /* FPU & Logical Operations */
2575 {
2576 unsigned int xop = GET_FIELD(insn, 7, 12);
e7d51b34 2577 TCGv cpu_dst = get_temp_tl(dc);
de9e9d9f 2578 TCGv cpu_tmp0;
5793f2a4 2579
0f8a249a 2580 if (xop == 0x3a) { /* generate trap */
bd49ed41
RH
2581 int cond = GET_FIELD(insn, 3, 6);
2582 TCGv_i32 trap;
42a268c2
RH
2583 TCGLabel *l1 = NULL;
2584 int mask;
3475187d 2585
bd49ed41
RH
2586 if (cond == 0) {
2587 /* Trap never. */
2588 break;
cf495bcf 2589 }
b04d9890 2590
bd49ed41 2591 save_state(dc);
b04d9890 2592
bd49ed41
RH
2593 if (cond != 8) {
2594 /* Conditional trap. */
3a49e759 2595 DisasCompare cmp;
3475187d 2596#ifdef TARGET_SPARC64
0f8a249a
BS
2597 /* V9 icc/xcc */
2598 int cc = GET_FIELD_SP(insn, 11, 12);
3a49e759
RH
2599 if (cc == 0) {
2600 gen_compare(&cmp, 0, cond, dc);
2601 } else if (cc == 2) {
2602 gen_compare(&cmp, 1, cond, dc);
2603 } else {
0f8a249a 2604 goto illegal_insn;
3a49e759 2605 }
3475187d 2606#else
3a49e759 2607 gen_compare(&cmp, 0, cond, dc);
3475187d 2608#endif
b158a785 2609 l1 = gen_new_label();
3a49e759
RH
2610 tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
2611 cmp.c1, cmp.c2, l1);
2612 free_compare(&cmp);
bd49ed41 2613 }
b158a785 2614
bd49ed41
RH
2615 mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
2616 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
2617
2618 /* Don't use the normal temporaries, as they may well have
2619 gone out of scope with the branch above. While we're
2620 doing that we might as well pre-truncate to 32-bit. */
2621 trap = tcg_temp_new_i32();
2622
2623 rs1 = GET_FIELD_SP(insn, 14, 18);
2624 if (IS_IMM) {
2625 rs2 = GET_FIELD_SP(insn, 0, 6);
2626 if (rs1 == 0) {
2627 tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP);
2628 /* Signal that the trap value is fully constant. */
2629 mask = 0;
2630 } else {
97ea2859 2631 TCGv t1 = gen_load_gpr(dc, rs1);
bd49ed41 2632 tcg_gen_trunc_tl_i32(trap, t1);
bd49ed41
RH
2633 tcg_gen_addi_i32(trap, trap, rs2);
2634 }
2635 } else {
97ea2859 2636 TCGv t1, t2;
bd49ed41 2637 rs2 = GET_FIELD_SP(insn, 0, 4);
97ea2859
RH
2638 t1 = gen_load_gpr(dc, rs1);
2639 t2 = gen_load_gpr(dc, rs2);
bd49ed41
RH
2640 tcg_gen_add_tl(t1, t1, t2);
2641 tcg_gen_trunc_tl_i32(trap, t1);
bd49ed41
RH
2642 }
2643 if (mask != 0) {
2644 tcg_gen_andi_i32(trap, trap, mask);
2645 tcg_gen_addi_i32(trap, trap, TT_TRAP);
2646 }
2647
2648 gen_helper_raise_exception(cpu_env, trap);
2649 tcg_temp_free_i32(trap);
b158a785 2650
fe1755cb
RH
2651 if (cond == 8) {
2652 /* An unconditional trap ends the TB. */
2653 dc->is_br = 1;
2654 goto jmp_insn;
2655 } else {
2656 /* A conditional trap falls through to the next insn. */
b158a785 2657 gen_set_label(l1);
fe1755cb 2658 break;
cf495bcf
FB
2659 }
2660 } else if (xop == 0x28) {
2661 rs1 = GET_FIELD(insn, 13, 17);
2662 switch(rs1) {
2663 case 0: /* rdy */
65fe7b09
BS
2664#ifndef TARGET_SPARC64
2665 case 0x01 ... 0x0e: /* undefined in the SPARCv8
2666 manual, rdy on the microSPARC
2667 II */
2668 case 0x0f: /* stbar in the SPARCv8 manual,
2669 rdy on the microSPARC II */
2670 case 0x10 ... 0x1f: /* implementation-dependent in the
2671 SPARCv8 manual, rdy on the
2672 microSPARC II */
4a2ba232
FC
2673 /* Read Asr17 */
2674 if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
97ea2859 2675 TCGv t = gen_dest_gpr(dc, rd);
4a2ba232 2676 /* Read Asr17 for a Leon3 monoprocessor */
97ea2859
RH
2677 tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1));
2678 gen_store_gpr(dc, rd, t);
4a2ba232
FC
2679 break;
2680 }
65fe7b09 2681#endif
97ea2859 2682 gen_store_gpr(dc, rd, cpu_y);
cf495bcf 2683 break;
3475187d 2684#ifdef TARGET_SPARC64
0f8a249a 2685 case 0x2: /* V9 rdccr */
20132b96 2686 update_psr(dc);
063c3675 2687 gen_helper_rdccr(cpu_dst, cpu_env);
97ea2859 2688 gen_store_gpr(dc, rd, cpu_dst);
3475187d 2689 break;
0f8a249a 2690 case 0x3: /* V9 rdasi */
255e1fcb 2691 tcg_gen_ext_i32_tl(cpu_dst, cpu_asi);
97ea2859 2692 gen_store_gpr(dc, rd, cpu_dst);
3475187d 2693 break;
0f8a249a 2694 case 0x4: /* V9 rdtick */
ccd4a219 2695 {
a7812ae4 2696 TCGv_ptr r_tickptr;
c9a46442 2697 TCGv_i32 r_const;
ccd4a219 2698
a7812ae4 2699 r_tickptr = tcg_temp_new_ptr();
c9a46442 2700 r_const = tcg_const_i32(dc->mem_idx);
ccd4a219 2701 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 2702 offsetof(CPUSPARCState, tick));
c9a46442
MCA
2703 gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
2704 r_const);
a7812ae4 2705 tcg_temp_free_ptr(r_tickptr);
c9a46442 2706 tcg_temp_free_i32(r_const);
97ea2859 2707 gen_store_gpr(dc, rd, cpu_dst);
ccd4a219 2708 }
3475187d 2709 break;
0f8a249a 2710 case 0x5: /* V9 rdpc */
2ea815ca 2711 {
97ea2859 2712 TCGv t = gen_dest_gpr(dc, rd);
22036a49 2713 if (unlikely(AM_CHECK(dc))) {
97ea2859 2714 tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL);
22036a49 2715 } else {
97ea2859 2716 tcg_gen_movi_tl(t, dc->pc);
22036a49 2717 }
97ea2859 2718 gen_store_gpr(dc, rd, t);
2ea815ca 2719 }
0f8a249a
BS
2720 break;
2721 case 0x6: /* V9 rdfprs */
255e1fcb 2722 tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
97ea2859 2723 gen_store_gpr(dc, rd, cpu_dst);
3475187d 2724 break;
65fe7b09
BS
2725 case 0xf: /* V9 membar */
2726 break; /* no effect */
0f8a249a 2727 case 0x13: /* Graphics Status */
5b12f1e8 2728 if (gen_trap_ifnofpu(dc)) {
725cb90b 2729 goto jmp_insn;
5b12f1e8 2730 }
97ea2859 2731 gen_store_gpr(dc, rd, cpu_gsr);
725cb90b 2732 break;
9d926598 2733 case 0x16: /* Softint */
e86ceb0d
RH
2734 tcg_gen_ld32s_tl(cpu_dst, cpu_env,
2735 offsetof(CPUSPARCState, softint));
97ea2859 2736 gen_store_gpr(dc, rd, cpu_dst);
9d926598 2737 break;
0f8a249a 2738 case 0x17: /* Tick compare */
97ea2859 2739 gen_store_gpr(dc, rd, cpu_tick_cmpr);
83469015 2740 break;
0f8a249a 2741 case 0x18: /* System tick */
ccd4a219 2742 {
a7812ae4 2743 TCGv_ptr r_tickptr;
c9a46442 2744 TCGv_i32 r_const;
ccd4a219 2745
a7812ae4 2746 r_tickptr = tcg_temp_new_ptr();
c9a46442 2747 r_const = tcg_const_i32(dc->mem_idx);
ccd4a219 2748 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 2749 offsetof(CPUSPARCState, stick));
c9a46442
MCA
2750 gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
2751 r_const);
a7812ae4 2752 tcg_temp_free_ptr(r_tickptr);
c9a46442 2753 tcg_temp_free_i32(r_const);
97ea2859 2754 gen_store_gpr(dc, rd, cpu_dst);
ccd4a219 2755 }
83469015 2756 break;
0f8a249a 2757 case 0x19: /* System tick compare */
97ea2859 2758 gen_store_gpr(dc, rd, cpu_stick_cmpr);
83469015 2759 break;
0f8a249a
BS
2760 case 0x10: /* Performance Control */
2761 case 0x11: /* Performance Instrumentation Counter */
2762 case 0x12: /* Dispatch Control */
2763 case 0x14: /* Softint set, WO */
2764 case 0x15: /* Softint clear, WO */
3475187d
FB
2765#endif
2766 default:
cf495bcf
FB
2767 goto illegal_insn;
2768 }
e8af50a3 2769#if !defined(CONFIG_USER_ONLY)
e9ebed4d 2770 } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
3475187d 2771#ifndef TARGET_SPARC64
20132b96 2772 if (!supervisor(dc)) {
0f8a249a 2773 goto priv_insn;
20132b96
RH
2774 }
2775 update_psr(dc);
063c3675 2776 gen_helper_rdpsr(cpu_dst, cpu_env);
e9ebed4d 2777#else
fb79ceb9 2778 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
2779 if (!hypervisor(dc))
2780 goto priv_insn;
2781 rs1 = GET_FIELD(insn, 13, 17);
2782 switch (rs1) {
2783 case 0: // hpstate
2784 // gen_op_rdhpstate();
2785 break;
2786 case 1: // htstate
2787 // gen_op_rdhtstate();
2788 break;
2789 case 3: // hintp
255e1fcb 2790 tcg_gen_mov_tl(cpu_dst, cpu_hintp);
e9ebed4d
BS
2791 break;
2792 case 5: // htba
255e1fcb 2793 tcg_gen_mov_tl(cpu_dst, cpu_htba);
e9ebed4d
BS
2794 break;
2795 case 6: // hver
255e1fcb 2796 tcg_gen_mov_tl(cpu_dst, cpu_hver);
e9ebed4d
BS
2797 break;
2798 case 31: // hstick_cmpr
255e1fcb 2799 tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
e9ebed4d
BS
2800 break;
2801 default:
2802 goto illegal_insn;
2803 }
2804#endif
97ea2859 2805 gen_store_gpr(dc, rd, cpu_dst);
e8af50a3 2806 break;
3475187d 2807 } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
de9e9d9f 2808 if (!supervisor(dc)) {
0f8a249a 2809 goto priv_insn;
de9e9d9f
RH
2810 }
2811 cpu_tmp0 = get_temp_tl(dc);
3475187d
FB
2812#ifdef TARGET_SPARC64
2813 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2814 switch (rs1) {
2815 case 0: // tpc
375ee38b 2816 {
a7812ae4 2817 TCGv_ptr r_tsptr;
375ee38b 2818
a7812ae4 2819 r_tsptr = tcg_temp_new_ptr();
8194f35a 2820 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
a7812ae4 2821 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 2822 offsetof(trap_state, tpc));
a7812ae4 2823 tcg_temp_free_ptr(r_tsptr);
375ee38b 2824 }
0f8a249a
BS
2825 break;
2826 case 1: // tnpc
375ee38b 2827 {
a7812ae4 2828 TCGv_ptr r_tsptr;
375ee38b 2829
a7812ae4 2830 r_tsptr = tcg_temp_new_ptr();
8194f35a 2831 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 2832 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 2833 offsetof(trap_state, tnpc));
a7812ae4 2834 tcg_temp_free_ptr(r_tsptr);
375ee38b 2835 }
0f8a249a
BS
2836 break;
2837 case 2: // tstate
375ee38b 2838 {
a7812ae4 2839 TCGv_ptr r_tsptr;
375ee38b 2840
a7812ae4 2841 r_tsptr = tcg_temp_new_ptr();
8194f35a 2842 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 2843 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 2844 offsetof(trap_state, tstate));
a7812ae4 2845 tcg_temp_free_ptr(r_tsptr);
375ee38b 2846 }
0f8a249a
BS
2847 break;
2848 case 3: // tt
375ee38b 2849 {
45778f99 2850 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
375ee38b 2851
8194f35a 2852 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
45778f99
RH
2853 tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr,
2854 offsetof(trap_state, tt));
a7812ae4 2855 tcg_temp_free_ptr(r_tsptr);
375ee38b 2856 }
0f8a249a
BS
2857 break;
2858 case 4: // tick
ccd4a219 2859 {
a7812ae4 2860 TCGv_ptr r_tickptr;
c9a46442 2861 TCGv_i32 r_const;
ccd4a219 2862
a7812ae4 2863 r_tickptr = tcg_temp_new_ptr();
c9a46442 2864 r_const = tcg_const_i32(dc->mem_idx);
ccd4a219 2865 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 2866 offsetof(CPUSPARCState, tick));
c9a46442
MCA
2867 gen_helper_tick_get_count(cpu_tmp0, cpu_env,
2868 r_tickptr, r_const);
a7812ae4 2869 tcg_temp_free_ptr(r_tickptr);
c9a46442 2870 tcg_temp_free_i32(r_const);
ccd4a219 2871 }
0f8a249a
BS
2872 break;
2873 case 5: // tba
255e1fcb 2874 tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
0f8a249a
BS
2875 break;
2876 case 6: // pstate
45778f99
RH
2877 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2878 offsetof(CPUSPARCState, pstate));
0f8a249a
BS
2879 break;
2880 case 7: // tl
45778f99
RH
2881 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2882 offsetof(CPUSPARCState, tl));
0f8a249a
BS
2883 break;
2884 case 8: // pil
45778f99
RH
2885 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2886 offsetof(CPUSPARCState, psrpil));
0f8a249a
BS
2887 break;
2888 case 9: // cwp
063c3675 2889 gen_helper_rdcwp(cpu_tmp0, cpu_env);
0f8a249a
BS
2890 break;
2891 case 10: // cansave
45778f99
RH
2892 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2893 offsetof(CPUSPARCState, cansave));
0f8a249a
BS
2894 break;
2895 case 11: // canrestore
45778f99
RH
2896 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2897 offsetof(CPUSPARCState, canrestore));
0f8a249a
BS
2898 break;
2899 case 12: // cleanwin
45778f99
RH
2900 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2901 offsetof(CPUSPARCState, cleanwin));
0f8a249a
BS
2902 break;
2903 case 13: // otherwin
45778f99
RH
2904 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2905 offsetof(CPUSPARCState, otherwin));
0f8a249a
BS
2906 break;
2907 case 14: // wstate
45778f99
RH
2908 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2909 offsetof(CPUSPARCState, wstate));
0f8a249a 2910 break;
e9ebed4d 2911 case 16: // UA2005 gl
fb79ceb9 2912 CHECK_IU_FEATURE(dc, GL);
45778f99
RH
2913 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2914 offsetof(CPUSPARCState, gl));
e9ebed4d
BS
2915 break;
2916 case 26: // UA2005 strand status
fb79ceb9 2917 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
2918 if (!hypervisor(dc))
2919 goto priv_insn;
527067d8 2920 tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
e9ebed4d 2921 break;
0f8a249a 2922 case 31: // ver
255e1fcb 2923 tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
0f8a249a
BS
2924 break;
2925 case 15: // fq
2926 default:
2927 goto illegal_insn;
2928 }
3475187d 2929#else
255e1fcb 2930 tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
3475187d 2931#endif
97ea2859 2932 gen_store_gpr(dc, rd, cpu_tmp0);
e8af50a3 2933 break;
3475187d
FB
2934 } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
2935#ifdef TARGET_SPARC64
66442b07 2936 save_state(dc);
063c3675 2937 gen_helper_flushw(cpu_env);
3475187d 2938#else
0f8a249a
BS
2939 if (!supervisor(dc))
2940 goto priv_insn;
97ea2859 2941 gen_store_gpr(dc, rd, cpu_tbr);
3475187d 2942#endif
e8af50a3
FB
2943 break;
2944#endif
0f8a249a 2945 } else if (xop == 0x34) { /* FPU Operations */
5b12f1e8 2946 if (gen_trap_ifnofpu(dc)) {
a80dde08 2947 goto jmp_insn;
5b12f1e8 2948 }
0f8a249a 2949 gen_op_clear_ieee_excp_and_FTT();
e8af50a3 2950 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2951 rs2 = GET_FIELD(insn, 27, 31);
2952 xop = GET_FIELD(insn, 18, 26);
66442b07 2953 save_state(dc);
0f8a249a 2954 switch (xop) {
dc1a6971 2955 case 0x1: /* fmovs */
208ae657
RH
2956 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
2957 gen_store_fpr_F(dc, rd, cpu_src1_32);
dc1a6971
BS
2958 break;
2959 case 0x5: /* fnegs */
61f17f6e 2960 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
dc1a6971
BS
2961 break;
2962 case 0x9: /* fabss */
61f17f6e 2963 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
dc1a6971
BS
2964 break;
2965 case 0x29: /* fsqrts */
2966 CHECK_FPU_FEATURE(dc, FSQRT);
61f17f6e 2967 gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
dc1a6971
BS
2968 break;
2969 case 0x2a: /* fsqrtd */
2970 CHECK_FPU_FEATURE(dc, FSQRT);
61f17f6e 2971 gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
dc1a6971
BS
2972 break;
2973 case 0x2b: /* fsqrtq */
2974 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 2975 gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
dc1a6971
BS
2976 break;
2977 case 0x41: /* fadds */
61f17f6e 2978 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
dc1a6971
BS
2979 break;
2980 case 0x42: /* faddd */
61f17f6e 2981 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
dc1a6971
BS
2982 break;
2983 case 0x43: /* faddq */
2984 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 2985 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
dc1a6971
BS
2986 break;
2987 case 0x45: /* fsubs */
61f17f6e 2988 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
dc1a6971
BS
2989 break;
2990 case 0x46: /* fsubd */
61f17f6e 2991 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
dc1a6971
BS
2992 break;
2993 case 0x47: /* fsubq */
2994 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 2995 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
dc1a6971
BS
2996 break;
2997 case 0x49: /* fmuls */
2998 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 2999 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
dc1a6971
BS
3000 break;
3001 case 0x4a: /* fmuld */
3002 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3003 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
dc1a6971
BS
3004 break;
3005 case 0x4b: /* fmulq */
3006 CHECK_FPU_FEATURE(dc, FLOAT128);
3007 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3008 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
dc1a6971
BS
3009 break;
3010 case 0x4d: /* fdivs */
61f17f6e 3011 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
dc1a6971
BS
3012 break;
3013 case 0x4e: /* fdivd */
61f17f6e 3014 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
dc1a6971
BS
3015 break;
3016 case 0x4f: /* fdivq */
3017 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3018 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
dc1a6971
BS
3019 break;
3020 case 0x69: /* fsmuld */
3021 CHECK_FPU_FEATURE(dc, FSMULD);
61f17f6e 3022 gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
dc1a6971
BS
3023 break;
3024 case 0x6e: /* fdmulq */
3025 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3026 gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
dc1a6971
BS
3027 break;
3028 case 0xc4: /* fitos */
61f17f6e 3029 gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
dc1a6971
BS
3030 break;
3031 case 0xc6: /* fdtos */
61f17f6e 3032 gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
dc1a6971
BS
3033 break;
3034 case 0xc7: /* fqtos */
3035 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3036 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
dc1a6971
BS
3037 break;
3038 case 0xc8: /* fitod */
61f17f6e 3039 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
dc1a6971
BS
3040 break;
3041 case 0xc9: /* fstod */
61f17f6e 3042 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
dc1a6971
BS
3043 break;
3044 case 0xcb: /* fqtod */
3045 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3046 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
dc1a6971
BS
3047 break;
3048 case 0xcc: /* fitoq */
3049 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3050 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
dc1a6971
BS
3051 break;
3052 case 0xcd: /* fstoq */
3053 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3054 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
dc1a6971
BS
3055 break;
3056 case 0xce: /* fdtoq */
3057 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3058 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
dc1a6971
BS
3059 break;
3060 case 0xd1: /* fstoi */
61f17f6e 3061 gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
dc1a6971
BS
3062 break;
3063 case 0xd2: /* fdtoi */
61f17f6e 3064 gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
dc1a6971
BS
3065 break;
3066 case 0xd3: /* fqtoi */
3067 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3068 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
dc1a6971 3069 break;
3475187d 3070#ifdef TARGET_SPARC64
dc1a6971 3071 case 0x2: /* V9 fmovd */
96eda024
RH
3072 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
3073 gen_store_fpr_D(dc, rd, cpu_src1_64);
dc1a6971
BS
3074 break;
3075 case 0x3: /* V9 fmovq */
3076 CHECK_FPU_FEATURE(dc, FLOAT128);
ac11f776 3077 gen_move_Q(rd, rs2);
dc1a6971
BS
3078 break;
3079 case 0x6: /* V9 fnegd */
61f17f6e 3080 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
dc1a6971
BS
3081 break;
3082 case 0x7: /* V9 fnegq */
3083 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3084 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
dc1a6971
BS
3085 break;
3086 case 0xa: /* V9 fabsd */
61f17f6e 3087 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
dc1a6971
BS
3088 break;
3089 case 0xb: /* V9 fabsq */
3090 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3091 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
dc1a6971
BS
3092 break;
3093 case 0x81: /* V9 fstox */
61f17f6e 3094 gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
dc1a6971
BS
3095 break;
3096 case 0x82: /* V9 fdtox */
61f17f6e 3097 gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
dc1a6971
BS
3098 break;
3099 case 0x83: /* V9 fqtox */
3100 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3101 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
dc1a6971
BS
3102 break;
3103 case 0x84: /* V9 fxtos */
61f17f6e 3104 gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
dc1a6971
BS
3105 break;
3106 case 0x88: /* V9 fxtod */
61f17f6e 3107 gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
dc1a6971
BS
3108 break;
3109 case 0x8c: /* V9 fxtoq */
3110 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3111 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
dc1a6971 3112 break;
0f8a249a 3113#endif
dc1a6971
BS
3114 default:
3115 goto illegal_insn;
0f8a249a
BS
3116 }
3117 } else if (xop == 0x35) { /* FPU Operations */
3475187d 3118#ifdef TARGET_SPARC64
0f8a249a 3119 int cond;
3475187d 3120#endif
5b12f1e8 3121 if (gen_trap_ifnofpu(dc)) {
a80dde08 3122 goto jmp_insn;
5b12f1e8 3123 }
0f8a249a 3124 gen_op_clear_ieee_excp_and_FTT();
cf495bcf 3125 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
3126 rs2 = GET_FIELD(insn, 27, 31);
3127 xop = GET_FIELD(insn, 18, 26);
66442b07 3128 save_state(dc);
dcf24905 3129
690995a6
RH
3130#ifdef TARGET_SPARC64
3131#define FMOVR(sz) \
3132 do { \
3133 DisasCompare cmp; \
e7c8afb9 3134 cond = GET_FIELD_SP(insn, 10, 12); \
9d1d4e34 3135 cpu_src1 = get_src1(dc, insn); \
690995a6
RH
3136 gen_compare_reg(&cmp, cond, cpu_src1); \
3137 gen_fmov##sz(dc, &cmp, rd, rs2); \
3138 free_compare(&cmp); \
3139 } while (0)
3140
3141 if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
3142 FMOVR(s);
0f8a249a
BS
3143 break;
3144 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
690995a6 3145 FMOVR(d);
0f8a249a
BS
3146 break;
3147 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
64a88d5d 3148 CHECK_FPU_FEATURE(dc, FLOAT128);
690995a6 3149 FMOVR(q);
1f587329 3150 break;
0f8a249a 3151 }
690995a6 3152#undef FMOVR
0f8a249a
BS
3153#endif
3154 switch (xop) {
3475187d 3155#ifdef TARGET_SPARC64
7e480893
RH
3156#define FMOVCC(fcc, sz) \
3157 do { \
3158 DisasCompare cmp; \
714547bb 3159 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
3160 gen_fcompare(&cmp, fcc, cond); \
3161 gen_fmov##sz(dc, &cmp, rd, rs2); \
3162 free_compare(&cmp); \
3163 } while (0)
3164
0f8a249a 3165 case 0x001: /* V9 fmovscc %fcc0 */
7e480893 3166 FMOVCC(0, s);
0f8a249a
BS
3167 break;
3168 case 0x002: /* V9 fmovdcc %fcc0 */
7e480893 3169 FMOVCC(0, d);
0f8a249a
BS
3170 break;
3171 case 0x003: /* V9 fmovqcc %fcc0 */
64a88d5d 3172 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3173 FMOVCC(0, q);
1f587329 3174 break;
0f8a249a 3175 case 0x041: /* V9 fmovscc %fcc1 */
7e480893 3176 FMOVCC(1, s);
0f8a249a
BS
3177 break;
3178 case 0x042: /* V9 fmovdcc %fcc1 */
7e480893 3179 FMOVCC(1, d);
0f8a249a
BS
3180 break;
3181 case 0x043: /* V9 fmovqcc %fcc1 */
64a88d5d 3182 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3183 FMOVCC(1, q);
1f587329 3184 break;
0f8a249a 3185 case 0x081: /* V9 fmovscc %fcc2 */
7e480893 3186 FMOVCC(2, s);
0f8a249a
BS
3187 break;
3188 case 0x082: /* V9 fmovdcc %fcc2 */
7e480893 3189 FMOVCC(2, d);
0f8a249a
BS
3190 break;
3191 case 0x083: /* V9 fmovqcc %fcc2 */
64a88d5d 3192 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3193 FMOVCC(2, q);
1f587329 3194 break;
0f8a249a 3195 case 0x0c1: /* V9 fmovscc %fcc3 */
7e480893 3196 FMOVCC(3, s);
0f8a249a
BS
3197 break;
3198 case 0x0c2: /* V9 fmovdcc %fcc3 */
7e480893 3199 FMOVCC(3, d);
0f8a249a
BS
3200 break;
3201 case 0x0c3: /* V9 fmovqcc %fcc3 */
64a88d5d 3202 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3203 FMOVCC(3, q);
1f587329 3204 break;
7e480893
RH
3205#undef FMOVCC
3206#define FMOVCC(xcc, sz) \
3207 do { \
3208 DisasCompare cmp; \
714547bb 3209 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
3210 gen_compare(&cmp, xcc, cond, dc); \
3211 gen_fmov##sz(dc, &cmp, rd, rs2); \
3212 free_compare(&cmp); \
3213 } while (0)
19f329ad 3214
0f8a249a 3215 case 0x101: /* V9 fmovscc %icc */
7e480893 3216 FMOVCC(0, s);
0f8a249a
BS
3217 break;
3218 case 0x102: /* V9 fmovdcc %icc */
7e480893 3219 FMOVCC(0, d);
b7d69dc2 3220 break;
0f8a249a 3221 case 0x103: /* V9 fmovqcc %icc */
64a88d5d 3222 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3223 FMOVCC(0, q);
1f587329 3224 break;
0f8a249a 3225 case 0x181: /* V9 fmovscc %xcc */
7e480893 3226 FMOVCC(1, s);
0f8a249a
BS
3227 break;
3228 case 0x182: /* V9 fmovdcc %xcc */
7e480893 3229 FMOVCC(1, d);
0f8a249a
BS
3230 break;
3231 case 0x183: /* V9 fmovqcc %xcc */
64a88d5d 3232 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3233 FMOVCC(1, q);
1f587329 3234 break;
7e480893 3235#undef FMOVCC
1f587329
BS
3236#endif
3237 case 0x51: /* fcmps, V9 %fcc */
208ae657
RH
3238 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3239 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3240 gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a 3241 break;
1f587329 3242 case 0x52: /* fcmpd, V9 %fcc */
03fb8cfc
RH
3243 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3244 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3245 gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 3246 break;
1f587329 3247 case 0x53: /* fcmpq, V9 %fcc */
64a88d5d 3248 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
3249 gen_op_load_fpr_QT0(QFPREG(rs1));
3250 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 3251 gen_op_fcmpq(rd & 3);
1f587329 3252 break;
0f8a249a 3253 case 0x55: /* fcmpes, V9 %fcc */
208ae657
RH
3254 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3255 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3256 gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a
BS
3257 break;
3258 case 0x56: /* fcmped, V9 %fcc */
03fb8cfc
RH
3259 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3260 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3261 gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 3262 break;
1f587329 3263 case 0x57: /* fcmpeq, V9 %fcc */
64a88d5d 3264 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
3265 gen_op_load_fpr_QT0(QFPREG(rs1));
3266 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 3267 gen_op_fcmpeq(rd & 3);
1f587329 3268 break;
0f8a249a
BS
3269 default:
3270 goto illegal_insn;
3271 }
0f8a249a 3272 } else if (xop == 0x2) {
97ea2859 3273 TCGv dst = gen_dest_gpr(dc, rd);
e80cfcfc 3274 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a 3275 if (rs1 == 0) {
97ea2859 3276 /* clr/mov shortcut : or %g0, x, y -> mov x, y */
0f8a249a 3277 if (IS_IMM) { /* immediate */
67526b20 3278 simm = GET_FIELDs(insn, 19, 31);
97ea2859
RH
3279 tcg_gen_movi_tl(dst, simm);
3280 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
3281 } else { /* register */
3282 rs2 = GET_FIELD(insn, 27, 31);
97ea2859
RH
3283 if (rs2 == 0) {
3284 tcg_gen_movi_tl(dst, 0);
3285 gen_store_gpr(dc, rd, dst);
3286 } else {
3287 cpu_src2 = gen_load_gpr(dc, rs2);
3288 gen_store_gpr(dc, rd, cpu_src2);
3289 }
0f8a249a 3290 }
0f8a249a 3291 } else {
9d1d4e34 3292 cpu_src1 = get_src1(dc, insn);
0f8a249a 3293 if (IS_IMM) { /* immediate */
67526b20 3294 simm = GET_FIELDs(insn, 19, 31);
97ea2859
RH
3295 tcg_gen_ori_tl(dst, cpu_src1, simm);
3296 gen_store_gpr(dc, rd, dst);
0f8a249a 3297 } else { /* register */
0f8a249a 3298 rs2 = GET_FIELD(insn, 27, 31);
97ea2859
RH
3299 if (rs2 == 0) {
3300 /* mov shortcut: or x, %g0, y -> mov x, y */
3301 gen_store_gpr(dc, rd, cpu_src1);
3302 } else {
3303 cpu_src2 = gen_load_gpr(dc, rs2);
3304 tcg_gen_or_tl(dst, cpu_src1, cpu_src2);
3305 gen_store_gpr(dc, rd, dst);
3306 }
0f8a249a 3307 }
0f8a249a 3308 }
83469015 3309#ifdef TARGET_SPARC64
0f8a249a 3310 } else if (xop == 0x25) { /* sll, V9 sllx */
9d1d4e34 3311 cpu_src1 = get_src1(dc, insn);
0f8a249a 3312 if (IS_IMM) { /* immediate */
67526b20 3313 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3314 if (insn & (1 << 12)) {
67526b20 3315 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3316 } else {
67526b20 3317 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
1a2fb1c0 3318 }
0f8a249a 3319 } else { /* register */
83469015 3320 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3321 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3322 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3323 if (insn & (1 << 12)) {
6ae20372 3324 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
1a2fb1c0 3325 } else {
6ae20372 3326 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
1a2fb1c0 3327 }
01b1fa6d 3328 tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
83469015 3329 }
97ea2859 3330 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a 3331 } else if (xop == 0x26) { /* srl, V9 srlx */
9d1d4e34 3332 cpu_src1 = get_src1(dc, insn);
0f8a249a 3333 if (IS_IMM) { /* immediate */
67526b20 3334 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3335 if (insn & (1 << 12)) {
67526b20 3336 tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3337 } else {
6ae20372 3338 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
67526b20 3339 tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
1a2fb1c0 3340 }
0f8a249a 3341 } else { /* register */
83469015 3342 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3343 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3344 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3345 if (insn & (1 << 12)) {
6ae20372
BS
3346 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3347 tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
1a2fb1c0 3348 } else {
6ae20372
BS
3349 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3350 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
3351 tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
1a2fb1c0 3352 }
83469015 3353 }
97ea2859 3354 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a 3355 } else if (xop == 0x27) { /* sra, V9 srax */
9d1d4e34 3356 cpu_src1 = get_src1(dc, insn);
0f8a249a 3357 if (IS_IMM) { /* immediate */
67526b20 3358 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3359 if (insn & (1 << 12)) {
67526b20 3360 tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3361 } else {
97ea2859 3362 tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
67526b20 3363 tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
1a2fb1c0 3364 }
0f8a249a 3365 } else { /* register */
83469015 3366 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3367 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3368 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3369 if (insn & (1 << 12)) {
6ae20372
BS
3370 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3371 tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
1a2fb1c0 3372 } else {
6ae20372 3373 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
97ea2859 3374 tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
6ae20372 3375 tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
1a2fb1c0 3376 }
83469015 3377 }
97ea2859 3378 gen_store_gpr(dc, rd, cpu_dst);
e80cfcfc 3379#endif
fcc72045 3380 } else if (xop < 0x36) {
cf495bcf 3381 if (xop < 0x20) {
9d1d4e34
RH
3382 cpu_src1 = get_src1(dc, insn);
3383 cpu_src2 = get_src2(dc, insn);
cf495bcf 3384 switch (xop & ~0x10) {
b89e94af 3385 case 0x0: /* add */
97ea2859
RH
3386 if (xop & 0x10) {
3387 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
3388 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3389 dc->cc_op = CC_OP_ADD;
41d72852 3390 } else {
97ea2859 3391 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3392 }
cf495bcf 3393 break;
b89e94af 3394 case 0x1: /* and */
97ea2859 3395 tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3396 if (xop & 0x10) {
38482a77
BS
3397 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3398 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3399 dc->cc_op = CC_OP_LOGIC;
41d72852 3400 }
cf495bcf 3401 break;
b89e94af 3402 case 0x2: /* or */
97ea2859 3403 tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3404 if (xop & 0x10) {
38482a77
BS
3405 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3406 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3407 dc->cc_op = CC_OP_LOGIC;
8393617c 3408 }
0f8a249a 3409 break;
b89e94af 3410 case 0x3: /* xor */
97ea2859 3411 tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3412 if (xop & 0x10) {
38482a77
BS
3413 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3414 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3415 dc->cc_op = CC_OP_LOGIC;
8393617c 3416 }
cf495bcf 3417 break;
b89e94af 3418 case 0x4: /* sub */
97ea2859
RH
3419 if (xop & 0x10) {
3420 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
3421 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
3422 dc->cc_op = CC_OP_SUB;
41d72852 3423 } else {
97ea2859 3424 tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3425 }
cf495bcf 3426 break;
b89e94af 3427 case 0x5: /* andn */
97ea2859 3428 tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3429 if (xop & 0x10) {
38482a77
BS
3430 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3431 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3432 dc->cc_op = CC_OP_LOGIC;
8393617c 3433 }
cf495bcf 3434 break;
b89e94af 3435 case 0x6: /* orn */
97ea2859 3436 tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3437 if (xop & 0x10) {
38482a77
BS
3438 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3439 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3440 dc->cc_op = CC_OP_LOGIC;
8393617c 3441 }
cf495bcf 3442 break;
b89e94af 3443 case 0x7: /* xorn */
97ea2859 3444 tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3445 if (xop & 0x10) {
38482a77
BS
3446 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3447 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3448 dc->cc_op = CC_OP_LOGIC;
8393617c 3449 }
cf495bcf 3450 break;
b89e94af 3451 case 0x8: /* addx, V9 addc */
70c48285
RH
3452 gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
3453 (xop & 0x10));
cf495bcf 3454 break;
ded3ab80 3455#ifdef TARGET_SPARC64
0f8a249a 3456 case 0x9: /* V9 mulx */
97ea2859 3457 tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2);
ded3ab80
PB
3458 break;
3459#endif
b89e94af 3460 case 0xa: /* umul */
64a88d5d 3461 CHECK_IU_FEATURE(dc, MUL);
6ae20372 3462 gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
8393617c 3463 if (xop & 0x10) {
38482a77
BS
3464 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3465 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3466 dc->cc_op = CC_OP_LOGIC;
8393617c 3467 }
cf495bcf 3468 break;
b89e94af 3469 case 0xb: /* smul */
64a88d5d 3470 CHECK_IU_FEATURE(dc, MUL);
6ae20372 3471 gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
8393617c 3472 if (xop & 0x10) {
38482a77
BS
3473 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3474 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3475 dc->cc_op = CC_OP_LOGIC;
8393617c 3476 }
cf495bcf 3477 break;
b89e94af 3478 case 0xc: /* subx, V9 subc */
70c48285
RH
3479 gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
3480 (xop & 0x10));
cf495bcf 3481 break;
ded3ab80 3482#ifdef TARGET_SPARC64
0f8a249a 3483 case 0xd: /* V9 udivx */
c28ae41e 3484 gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
ded3ab80
PB
3485 break;
3486#endif
b89e94af 3487 case 0xe: /* udiv */
64a88d5d 3488 CHECK_IU_FEATURE(dc, DIV);
8393617c 3489 if (xop & 0x10) {
7a5e4488
BS
3490 gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
3491 cpu_src2);
6c78ea32 3492 dc->cc_op = CC_OP_DIV;
0fcec41e 3493 } else {
7a5e4488
BS
3494 gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
3495 cpu_src2);
8393617c 3496 }
cf495bcf 3497 break;
b89e94af 3498 case 0xf: /* sdiv */
64a88d5d 3499 CHECK_IU_FEATURE(dc, DIV);
8393617c 3500 if (xop & 0x10) {
7a5e4488
BS
3501 gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
3502 cpu_src2);
6c78ea32 3503 dc->cc_op = CC_OP_DIV;
0fcec41e 3504 } else {
7a5e4488
BS
3505 gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
3506 cpu_src2);
8393617c 3507 }
cf495bcf
FB
3508 break;
3509 default:
3510 goto illegal_insn;
3511 }
97ea2859 3512 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3513 } else {
9d1d4e34
RH
3514 cpu_src1 = get_src1(dc, insn);
3515 cpu_src2 = get_src2(dc, insn);
cf495bcf 3516 switch (xop) {
0f8a249a 3517 case 0x20: /* taddcc */
a2ea4aa9 3518 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 3519 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92
BS
3520 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
3521 dc->cc_op = CC_OP_TADD;
0f8a249a
BS
3522 break;
3523 case 0x21: /* tsubcc */
a2ea4aa9 3524 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 3525 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92
BS
3526 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
3527 dc->cc_op = CC_OP_TSUB;
0f8a249a
BS
3528 break;
3529 case 0x22: /* taddcctv */
a2ea4aa9
RH
3530 gen_helper_taddcctv(cpu_dst, cpu_env,
3531 cpu_src1, cpu_src2);
97ea2859 3532 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92 3533 dc->cc_op = CC_OP_TADDTV;
0f8a249a
BS
3534 break;
3535 case 0x23: /* tsubcctv */
a2ea4aa9
RH
3536 gen_helper_tsubcctv(cpu_dst, cpu_env,
3537 cpu_src1, cpu_src2);
97ea2859 3538 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92 3539 dc->cc_op = CC_OP_TSUBTV;
0f8a249a 3540 break;
cf495bcf 3541 case 0x24: /* mulscc */
20132b96 3542 update_psr(dc);
6ae20372 3543 gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 3544 gen_store_gpr(dc, rd, cpu_dst);
d084469c
BS
3545 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3546 dc->cc_op = CC_OP_ADD;
cf495bcf 3547 break;
83469015 3548#ifndef TARGET_SPARC64
0f8a249a 3549 case 0x25: /* sll */
e35298cd 3550 if (IS_IMM) { /* immediate */
67526b20
BS
3551 simm = GET_FIELDs(insn, 20, 31);
3552 tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 3553 } else { /* register */
de9e9d9f 3554 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
3555 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3556 tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
3557 }
97ea2859 3558 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3559 break;
83469015 3560 case 0x26: /* srl */
e35298cd 3561 if (IS_IMM) { /* immediate */
67526b20
BS
3562 simm = GET_FIELDs(insn, 20, 31);
3563 tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 3564 } else { /* register */
de9e9d9f 3565 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
3566 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3567 tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
3568 }
97ea2859 3569 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3570 break;
83469015 3571 case 0x27: /* sra */
e35298cd 3572 if (IS_IMM) { /* immediate */
67526b20
BS
3573 simm = GET_FIELDs(insn, 20, 31);
3574 tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 3575 } else { /* register */
de9e9d9f 3576 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
3577 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3578 tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
3579 }
97ea2859 3580 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3581 break;
83469015 3582#endif
cf495bcf
FB
3583 case 0x30:
3584 {
de9e9d9f 3585 cpu_tmp0 = get_temp_tl(dc);
cf495bcf 3586 switch(rd) {
3475187d 3587 case 0: /* wry */
5068cbd9
BS
3588 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3589 tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
cf495bcf 3590 break;
65fe7b09
BS
3591#ifndef TARGET_SPARC64
3592 case 0x01 ... 0x0f: /* undefined in the
3593 SPARCv8 manual, nop
3594 on the microSPARC
3595 II */
3596 case 0x10 ... 0x1f: /* implementation-dependent
3597 in the SPARCv8
3598 manual, nop on the
3599 microSPARC II */
d1c36ba7
RH
3600 if ((rd == 0x13) && (dc->def->features &
3601 CPU_FEATURE_POWERDOWN)) {
3602 /* LEON3 power-down */
1cf892ca 3603 save_state(dc);
d1c36ba7
RH
3604 gen_helper_power_down(cpu_env);
3605 }
65fe7b09
BS
3606 break;
3607#else
0f8a249a 3608 case 0x2: /* V9 wrccr */
7b04bd5c
RH
3609 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3610 gen_helper_wrccr(cpu_env, cpu_tmp0);
8393617c
BS
3611 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3612 dc->cc_op = CC_OP_FLAGS;
0f8a249a
BS
3613 break;
3614 case 0x3: /* V9 wrasi */
7b04bd5c
RH
3615 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3616 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff);
3617 tcg_gen_trunc_tl_i32(cpu_asi, cpu_tmp0);
0f8a249a
BS
3618 break;
3619 case 0x6: /* V9 wrfprs */
7b04bd5c
RH
3620 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3621 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0);
66442b07 3622 save_state(dc);
3299908c 3623 gen_op_next_insn();
57fec1fe 3624 tcg_gen_exit_tb(0);
3299908c 3625 dc->is_br = 1;
0f8a249a
BS
3626 break;
3627 case 0xf: /* V9 sir, nop if user */
3475187d 3628#if !defined(CONFIG_USER_ONLY)
6ad6135d 3629 if (supervisor(dc)) {
1a2fb1c0 3630 ; // XXX
6ad6135d 3631 }
3475187d 3632#endif
0f8a249a
BS
3633 break;
3634 case 0x13: /* Graphics Status */
5b12f1e8 3635 if (gen_trap_ifnofpu(dc)) {
725cb90b 3636 goto jmp_insn;
5b12f1e8 3637 }
255e1fcb 3638 tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
0f8a249a 3639 break;
9d926598
BS
3640 case 0x14: /* Softint set */
3641 if (!supervisor(dc))
3642 goto illegal_insn;
aeff993c
RH
3643 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3644 gen_helper_set_softint(cpu_env, cpu_tmp0);
9d926598
BS
3645 break;
3646 case 0x15: /* Softint clear */
3647 if (!supervisor(dc))
3648 goto illegal_insn;
aeff993c
RH
3649 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3650 gen_helper_clear_softint(cpu_env, cpu_tmp0);
9d926598
BS
3651 break;
3652 case 0x16: /* Softint write */
3653 if (!supervisor(dc))
3654 goto illegal_insn;
aeff993c
RH
3655 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3656 gen_helper_write_softint(cpu_env, cpu_tmp0);
9d926598 3657 break;
0f8a249a 3658 case 0x17: /* Tick compare */
83469015 3659#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
3660 if (!supervisor(dc))
3661 goto illegal_insn;
83469015 3662#endif
ccd4a219 3663 {
a7812ae4 3664 TCGv_ptr r_tickptr;
ccd4a219 3665
255e1fcb 3666 tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
6ae20372 3667 cpu_src2);
a7812ae4 3668 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3669 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3670 offsetof(CPUSPARCState, tick));
a7812ae4
PB
3671 gen_helper_tick_set_limit(r_tickptr,
3672 cpu_tick_cmpr);
3673 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3674 }
0f8a249a
BS
3675 break;
3676 case 0x18: /* System tick */
83469015 3677#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
3678 if (!supervisor(dc))
3679 goto illegal_insn;
83469015 3680#endif
ccd4a219 3681 {
a7812ae4 3682 TCGv_ptr r_tickptr;
ccd4a219 3683
7b04bd5c 3684 tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
6ae20372 3685 cpu_src2);
a7812ae4 3686 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3687 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3688 offsetof(CPUSPARCState, stick));
a7812ae4 3689 gen_helper_tick_set_count(r_tickptr,
7b04bd5c 3690 cpu_tmp0);
a7812ae4 3691 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3692 }
0f8a249a
BS
3693 break;
3694 case 0x19: /* System tick compare */
83469015 3695#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
3696 if (!supervisor(dc))
3697 goto illegal_insn;
3475187d 3698#endif
ccd4a219 3699 {
a7812ae4 3700 TCGv_ptr r_tickptr;
ccd4a219 3701
255e1fcb 3702 tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
6ae20372 3703 cpu_src2);
a7812ae4 3704 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3705 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3706 offsetof(CPUSPARCState, stick));
a7812ae4
PB
3707 gen_helper_tick_set_limit(r_tickptr,
3708 cpu_stick_cmpr);
3709 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3710 }
0f8a249a 3711 break;
83469015 3712
0f8a249a 3713 case 0x10: /* Performance Control */
77f193da
BS
3714 case 0x11: /* Performance Instrumentation
3715 Counter */
0f8a249a 3716 case 0x12: /* Dispatch Control */
83469015 3717#endif
3475187d 3718 default:
cf495bcf
FB
3719 goto illegal_insn;
3720 }
3721 }
3722 break;
e8af50a3 3723#if !defined(CONFIG_USER_ONLY)
af7bf89b 3724 case 0x31: /* wrpsr, V9 saved, restored */
e8af50a3 3725 {
0f8a249a
BS
3726 if (!supervisor(dc))
3727 goto priv_insn;
3475187d 3728#ifdef TARGET_SPARC64
0f8a249a
BS
3729 switch (rd) {
3730 case 0:
063c3675 3731 gen_helper_saved(cpu_env);
0f8a249a
BS
3732 break;
3733 case 1:
063c3675 3734 gen_helper_restored(cpu_env);
0f8a249a 3735 break;
e9ebed4d
BS
3736 case 2: /* UA2005 allclean */
3737 case 3: /* UA2005 otherw */
3738 case 4: /* UA2005 normalw */
3739 case 5: /* UA2005 invalw */
3740 // XXX
0f8a249a 3741 default:
3475187d
FB
3742 goto illegal_insn;
3743 }
3744#else
de9e9d9f 3745 cpu_tmp0 = get_temp_tl(dc);
7b04bd5c
RH
3746 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3747 gen_helper_wrpsr(cpu_env, cpu_tmp0);
8393617c
BS
3748 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3749 dc->cc_op = CC_OP_FLAGS;
66442b07 3750 save_state(dc);
9e61bde5 3751 gen_op_next_insn();
57fec1fe 3752 tcg_gen_exit_tb(0);
0f8a249a 3753 dc->is_br = 1;
3475187d 3754#endif
e8af50a3
FB
3755 }
3756 break;
af7bf89b 3757 case 0x32: /* wrwim, V9 wrpr */
e8af50a3 3758 {
0f8a249a
BS
3759 if (!supervisor(dc))
3760 goto priv_insn;
de9e9d9f 3761 cpu_tmp0 = get_temp_tl(dc);
ece43b8d 3762 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3475187d 3763#ifdef TARGET_SPARC64
0f8a249a
BS
3764 switch (rd) {
3765 case 0: // tpc
375ee38b 3766 {
a7812ae4 3767 TCGv_ptr r_tsptr;
375ee38b 3768
a7812ae4 3769 r_tsptr = tcg_temp_new_ptr();
8194f35a 3770 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3771 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
375ee38b 3772 offsetof(trap_state, tpc));
a7812ae4 3773 tcg_temp_free_ptr(r_tsptr);
375ee38b 3774 }
0f8a249a
BS
3775 break;
3776 case 1: // tnpc
375ee38b 3777 {
a7812ae4 3778 TCGv_ptr r_tsptr;
375ee38b 3779
a7812ae4 3780 r_tsptr = tcg_temp_new_ptr();
8194f35a 3781 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3782 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
375ee38b 3783 offsetof(trap_state, tnpc));
a7812ae4 3784 tcg_temp_free_ptr(r_tsptr);
375ee38b 3785 }
0f8a249a
BS
3786 break;
3787 case 2: // tstate
375ee38b 3788 {
a7812ae4 3789 TCGv_ptr r_tsptr;
375ee38b 3790
a7812ae4 3791 r_tsptr = tcg_temp_new_ptr();
8194f35a 3792 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3793 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
77f193da
BS
3794 offsetof(trap_state,
3795 tstate));
a7812ae4 3796 tcg_temp_free_ptr(r_tsptr);
375ee38b 3797 }
0f8a249a
BS
3798 break;
3799 case 3: // tt
375ee38b 3800 {
a7812ae4 3801 TCGv_ptr r_tsptr;
375ee38b 3802
a7812ae4 3803 r_tsptr = tcg_temp_new_ptr();
8194f35a 3804 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
7b9e066b
RH
3805 tcg_gen_st32_tl(cpu_tmp0, r_tsptr,
3806 offsetof(trap_state, tt));
a7812ae4 3807 tcg_temp_free_ptr(r_tsptr);
375ee38b 3808 }
0f8a249a
BS
3809 break;
3810 case 4: // tick
ccd4a219 3811 {
a7812ae4 3812 TCGv_ptr r_tickptr;
ccd4a219 3813
a7812ae4 3814 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3815 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3816 offsetof(CPUSPARCState, tick));
a7812ae4
PB
3817 gen_helper_tick_set_count(r_tickptr,
3818 cpu_tmp0);
3819 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3820 }
0f8a249a
BS
3821 break;
3822 case 5: // tba
255e1fcb 3823 tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
0f8a249a
BS
3824 break;
3825 case 6: // pstate
6234ac09
RH
3826 save_state(dc);
3827 gen_helper_wrpstate(cpu_env, cpu_tmp0);
3828 dc->npc = DYNAMIC_PC;
0f8a249a
BS
3829 break;
3830 case 7: // tl
6234ac09 3831 save_state(dc);
7b9e066b 3832 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
6234ac09
RH
3833 offsetof(CPUSPARCState, tl));
3834 dc->npc = DYNAMIC_PC;
0f8a249a
BS
3835 break;
3836 case 8: // pil
063c3675 3837 gen_helper_wrpil(cpu_env, cpu_tmp0);
0f8a249a
BS
3838 break;
3839 case 9: // cwp
063c3675 3840 gen_helper_wrcwp(cpu_env, cpu_tmp0);
0f8a249a
BS
3841 break;
3842 case 10: // cansave
7b9e066b
RH
3843 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3844 offsetof(CPUSPARCState,
3845 cansave));
0f8a249a
BS
3846 break;
3847 case 11: // canrestore
7b9e066b
RH
3848 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3849 offsetof(CPUSPARCState,
3850 canrestore));
0f8a249a
BS
3851 break;
3852 case 12: // cleanwin
7b9e066b
RH
3853 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3854 offsetof(CPUSPARCState,
3855 cleanwin));
0f8a249a
BS
3856 break;
3857 case 13: // otherwin
7b9e066b
RH
3858 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3859 offsetof(CPUSPARCState,
3860 otherwin));
0f8a249a
BS
3861 break;
3862 case 14: // wstate
7b9e066b
RH
3863 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3864 offsetof(CPUSPARCState,
3865 wstate));
0f8a249a 3866 break;
e9ebed4d 3867 case 16: // UA2005 gl
fb79ceb9 3868 CHECK_IU_FEATURE(dc, GL);
7b9e066b
RH
3869 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3870 offsetof(CPUSPARCState, gl));
e9ebed4d
BS
3871 break;
3872 case 26: // UA2005 strand status
fb79ceb9 3873 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
3874 if (!hypervisor(dc))
3875 goto priv_insn;
527067d8 3876 tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
e9ebed4d 3877 break;
0f8a249a
BS
3878 default:
3879 goto illegal_insn;
3880 }
3475187d 3881#else
7b9e066b
RH
3882 tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0);
3883 if (dc->def->nwindows != 32) {
3884 tcg_gen_andi_tl(cpu_wim, cpu_wim,
c93e7817 3885 (1 << dc->def->nwindows) - 1);
7b9e066b 3886 }
3475187d 3887#endif
e8af50a3
FB
3888 }
3889 break;
e9ebed4d 3890 case 0x33: /* wrtbr, UA2005 wrhpr */
e8af50a3 3891 {
e9ebed4d 3892#ifndef TARGET_SPARC64
0f8a249a
BS
3893 if (!supervisor(dc))
3894 goto priv_insn;
255e1fcb 3895 tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
e9ebed4d 3896#else
fb79ceb9 3897 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
3898 if (!hypervisor(dc))
3899 goto priv_insn;
de9e9d9f 3900 cpu_tmp0 = get_temp_tl(dc);
ece43b8d 3901 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
e9ebed4d
BS
3902 switch (rd) {
3903 case 0: // hpstate
3904 // XXX gen_op_wrhpstate();
66442b07 3905 save_state(dc);
e9ebed4d 3906 gen_op_next_insn();
57fec1fe 3907 tcg_gen_exit_tb(0);
e9ebed4d
BS
3908 dc->is_br = 1;
3909 break;
3910 case 1: // htstate
3911 // XXX gen_op_wrhtstate();
3912 break;
3913 case 3: // hintp
255e1fcb 3914 tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
e9ebed4d
BS
3915 break;
3916 case 5: // htba
255e1fcb 3917 tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
e9ebed4d
BS
3918 break;
3919 case 31: // hstick_cmpr
ccd4a219 3920 {
a7812ae4 3921 TCGv_ptr r_tickptr;
ccd4a219 3922
255e1fcb 3923 tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
a7812ae4 3924 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3925 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3926 offsetof(CPUSPARCState, hstick));
a7812ae4
PB
3927 gen_helper_tick_set_limit(r_tickptr,
3928 cpu_hstick_cmpr);
3929 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3930 }
e9ebed4d
BS
3931 break;
3932 case 6: // hver readonly
3933 default:
3934 goto illegal_insn;
3935 }
3936#endif
e8af50a3
FB
3937 }
3938 break;
3939#endif
3475187d 3940#ifdef TARGET_SPARC64
0f8a249a
BS
3941 case 0x2c: /* V9 movcc */
3942 {
3943 int cc = GET_FIELD_SP(insn, 11, 12);
3944 int cond = GET_FIELD_SP(insn, 14, 17);
f52879b4 3945 DisasCompare cmp;
97ea2859 3946 TCGv dst;
00f219bf 3947
0f8a249a 3948 if (insn & (1 << 18)) {
f52879b4
RH
3949 if (cc == 0) {
3950 gen_compare(&cmp, 0, cond, dc);
3951 } else if (cc == 2) {
3952 gen_compare(&cmp, 1, cond, dc);
3953 } else {
0f8a249a 3954 goto illegal_insn;
f52879b4 3955 }
0f8a249a 3956 } else {
f52879b4 3957 gen_fcompare(&cmp, cc, cond);
0f8a249a 3958 }
00f219bf 3959
f52879b4
RH
3960 /* The get_src2 above loaded the normal 13-bit
3961 immediate field, not the 11-bit field we have
3962 in movcc. But it did handle the reg case. */
3963 if (IS_IMM) {
67526b20 3964 simm = GET_FIELD_SPs(insn, 0, 10);
f52879b4 3965 tcg_gen_movi_tl(cpu_src2, simm);
00f219bf 3966 }
f52879b4 3967
97ea2859
RH
3968 dst = gen_load_gpr(dc, rd);
3969 tcg_gen_movcond_tl(cmp.cond, dst,
f52879b4 3970 cmp.c1, cmp.c2,
97ea2859 3971 cpu_src2, dst);
f52879b4 3972 free_compare(&cmp);
97ea2859 3973 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
3974 break;
3975 }
3976 case 0x2d: /* V9 sdivx */
c28ae41e 3977 gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
97ea2859 3978 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a
BS
3979 break;
3980 case 0x2e: /* V9 popc */
97ea2859
RH
3981 gen_helper_popc(cpu_dst, cpu_src2);
3982 gen_store_gpr(dc, rd, cpu_dst);
3983 break;
0f8a249a
BS
3984 case 0x2f: /* V9 movr */
3985 {
3986 int cond = GET_FIELD_SP(insn, 10, 12);
c33f80f5 3987 DisasCompare cmp;
97ea2859 3988 TCGv dst;
00f219bf 3989
c33f80f5 3990 gen_compare_reg(&cmp, cond, cpu_src1);
2ea815ca 3991
c33f80f5
RH
3992 /* The get_src2 above loaded the normal 13-bit
3993 immediate field, not the 10-bit field we have
3994 in movr. But it did handle the reg case. */
3995 if (IS_IMM) {
67526b20 3996 simm = GET_FIELD_SPs(insn, 0, 9);
c33f80f5 3997 tcg_gen_movi_tl(cpu_src2, simm);
0f8a249a 3998 }
c33f80f5 3999
97ea2859
RH
4000 dst = gen_load_gpr(dc, rd);
4001 tcg_gen_movcond_tl(cmp.cond, dst,
c33f80f5 4002 cmp.c1, cmp.c2,
97ea2859 4003 cpu_src2, dst);
c33f80f5 4004 free_compare(&cmp);
97ea2859 4005 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
4006 break;
4007 }
4008#endif
4009 default:
4010 goto illegal_insn;
4011 }
4012 }
3299908c
BS
4013 } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4014#ifdef TARGET_SPARC64
4015 int opf = GET_FIELD_SP(insn, 5, 13);
4016 rs1 = GET_FIELD(insn, 13, 17);
4017 rs2 = GET_FIELD(insn, 27, 31);
5b12f1e8 4018 if (gen_trap_ifnofpu(dc)) {
e9ebed4d 4019 goto jmp_insn;
5b12f1e8 4020 }
3299908c
BS
4021
4022 switch (opf) {
e9ebed4d 4023 case 0x000: /* VIS I edge8cc */
6c073553 4024 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4025 cpu_src1 = gen_load_gpr(dc, rs1);
4026 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4027 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
97ea2859 4028 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4029 break;
e9ebed4d 4030 case 0x001: /* VIS II edge8n */
6c073553 4031 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4032 cpu_src1 = gen_load_gpr(dc, rs1);
4033 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4034 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
97ea2859 4035 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4036 break;
e9ebed4d 4037 case 0x002: /* VIS I edge8lcc */
6c073553 4038 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4039 cpu_src1 = gen_load_gpr(dc, rs1);
4040 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4041 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
97ea2859 4042 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4043 break;
e9ebed4d 4044 case 0x003: /* VIS II edge8ln */
6c073553 4045 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4046 cpu_src1 = gen_load_gpr(dc, rs1);
4047 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4048 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
97ea2859 4049 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4050 break;
e9ebed4d 4051 case 0x004: /* VIS I edge16cc */
6c073553 4052 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4053 cpu_src1 = gen_load_gpr(dc, rs1);
4054 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4055 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
97ea2859 4056 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4057 break;
e9ebed4d 4058 case 0x005: /* VIS II edge16n */
6c073553 4059 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4060 cpu_src1 = gen_load_gpr(dc, rs1);
4061 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4062 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
97ea2859 4063 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4064 break;
e9ebed4d 4065 case 0x006: /* VIS I edge16lcc */
6c073553 4066 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4067 cpu_src1 = gen_load_gpr(dc, rs1);
4068 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4069 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
97ea2859 4070 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4071 break;
e9ebed4d 4072 case 0x007: /* VIS II edge16ln */
6c073553 4073 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4074 cpu_src1 = gen_load_gpr(dc, rs1);
4075 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4076 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
97ea2859 4077 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4078 break;
e9ebed4d 4079 case 0x008: /* VIS I edge32cc */
6c073553 4080 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4081 cpu_src1 = gen_load_gpr(dc, rs1);
4082 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4083 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
97ea2859 4084 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4085 break;
e9ebed4d 4086 case 0x009: /* VIS II edge32n */
6c073553 4087 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4088 cpu_src1 = gen_load_gpr(dc, rs1);
4089 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4090 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
97ea2859 4091 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4092 break;
e9ebed4d 4093 case 0x00a: /* VIS I edge32lcc */
6c073553 4094 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4095 cpu_src1 = gen_load_gpr(dc, rs1);
4096 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4097 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
97ea2859 4098 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4099 break;
e9ebed4d 4100 case 0x00b: /* VIS II edge32ln */
6c073553 4101 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4102 cpu_src1 = gen_load_gpr(dc, rs1);
4103 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4104 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
97ea2859 4105 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4106 break;
e9ebed4d 4107 case 0x010: /* VIS I array8 */
64a88d5d 4108 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4109 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4110 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4111 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
97ea2859 4112 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4113 break;
4114 case 0x012: /* VIS I array16 */
64a88d5d 4115 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4116 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4117 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4118 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4119 tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
97ea2859 4120 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4121 break;
4122 case 0x014: /* VIS I array32 */
64a88d5d 4123 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4124 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4125 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4126 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4127 tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
97ea2859 4128 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d 4129 break;
3299908c 4130 case 0x018: /* VIS I alignaddr */
64a88d5d 4131 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4132 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4133 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 4134 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
97ea2859 4135 gen_store_gpr(dc, rd, cpu_dst);
3299908c
BS
4136 break;
4137 case 0x01a: /* VIS I alignaddrl */
add545ab 4138 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4139 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4140 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 4141 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
97ea2859 4142 gen_store_gpr(dc, rd, cpu_dst);
add545ab
RH
4143 break;
4144 case 0x019: /* VIS II bmask */
793a137a 4145 CHECK_FPU_FEATURE(dc, VIS2);
9d1d4e34
RH
4146 cpu_src1 = gen_load_gpr(dc, rs1);
4147 cpu_src2 = gen_load_gpr(dc, rs2);
793a137a
RH
4148 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4149 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
97ea2859 4150 gen_store_gpr(dc, rd, cpu_dst);
793a137a 4151 break;
e9ebed4d 4152 case 0x020: /* VIS I fcmple16 */
64a88d5d 4153 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4154 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4155 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4156 gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4157 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4158 break;
4159 case 0x022: /* VIS I fcmpne16 */
64a88d5d 4160 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4161 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4162 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4163 gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4164 gen_store_gpr(dc, rd, cpu_dst);
3299908c 4165 break;
e9ebed4d 4166 case 0x024: /* VIS I fcmple32 */
64a88d5d 4167 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4168 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4169 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4170 gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4171 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4172 break;
4173 case 0x026: /* VIS I fcmpne32 */
64a88d5d 4174 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4175 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4176 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4177 gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4178 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4179 break;
4180 case 0x028: /* VIS I fcmpgt16 */
64a88d5d 4181 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4182 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4183 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4184 gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4185 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4186 break;
4187 case 0x02a: /* VIS I fcmpeq16 */
64a88d5d 4188 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4189 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4190 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4191 gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4192 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4193 break;
4194 case 0x02c: /* VIS I fcmpgt32 */
64a88d5d 4195 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4196 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4197 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4198 gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4199 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4200 break;
4201 case 0x02e: /* VIS I fcmpeq32 */
64a88d5d 4202 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4203 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4204 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4205 gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4206 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4207 break;
4208 case 0x031: /* VIS I fmul8x16 */
64a88d5d 4209 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4210 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
e9ebed4d
BS
4211 break;
4212 case 0x033: /* VIS I fmul8x16au */
64a88d5d 4213 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4214 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
e9ebed4d
BS
4215 break;
4216 case 0x035: /* VIS I fmul8x16al */
64a88d5d 4217 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4218 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
e9ebed4d
BS
4219 break;
4220 case 0x036: /* VIS I fmul8sux16 */
64a88d5d 4221 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4222 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
e9ebed4d
BS
4223 break;
4224 case 0x037: /* VIS I fmul8ulx16 */
64a88d5d 4225 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4226 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
e9ebed4d
BS
4227 break;
4228 case 0x038: /* VIS I fmuld8sux16 */
64a88d5d 4229 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4230 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
e9ebed4d
BS
4231 break;
4232 case 0x039: /* VIS I fmuld8ulx16 */
64a88d5d 4233 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4234 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
e9ebed4d
BS
4235 break;
4236 case 0x03a: /* VIS I fpack32 */
2dedf314
RH
4237 CHECK_FPU_FEATURE(dc, VIS1);
4238 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
4239 break;
e9ebed4d 4240 case 0x03b: /* VIS I fpack16 */
2dedf314
RH
4241 CHECK_FPU_FEATURE(dc, VIS1);
4242 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 4243 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
4244 gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
4245 gen_store_fpr_F(dc, rd, cpu_dst_32);
4246 break;
e9ebed4d 4247 case 0x03d: /* VIS I fpackfix */
2dedf314
RH
4248 CHECK_FPU_FEATURE(dc, VIS1);
4249 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 4250 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
4251 gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
4252 gen_store_fpr_F(dc, rd, cpu_dst_32);
4253 break;
f888300b
RH
4254 case 0x03e: /* VIS I pdist */
4255 CHECK_FPU_FEATURE(dc, VIS1);
4256 gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
4257 break;
3299908c 4258 case 0x048: /* VIS I faligndata */
64a88d5d 4259 CHECK_FPU_FEATURE(dc, VIS1);
50c796f9 4260 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
3299908c 4261 break;
e9ebed4d 4262 case 0x04b: /* VIS I fpmerge */
64a88d5d 4263 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4264 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
e9ebed4d
BS
4265 break;
4266 case 0x04c: /* VIS II bshuffle */
793a137a
RH
4267 CHECK_FPU_FEATURE(dc, VIS2);
4268 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
4269 break;
e9ebed4d 4270 case 0x04d: /* VIS I fexpand */
64a88d5d 4271 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4272 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
e9ebed4d
BS
4273 break;
4274 case 0x050: /* VIS I fpadd16 */
64a88d5d 4275 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4276 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
e9ebed4d
BS
4277 break;
4278 case 0x051: /* VIS I fpadd16s */
64a88d5d 4279 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4280 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
e9ebed4d
BS
4281 break;
4282 case 0x052: /* VIS I fpadd32 */
64a88d5d 4283 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4284 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
e9ebed4d
BS
4285 break;
4286 case 0x053: /* VIS I fpadd32s */
64a88d5d 4287 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4288 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
e9ebed4d
BS
4289 break;
4290 case 0x054: /* VIS I fpsub16 */
64a88d5d 4291 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4292 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
e9ebed4d
BS
4293 break;
4294 case 0x055: /* VIS I fpsub16s */
64a88d5d 4295 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4296 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
e9ebed4d
BS
4297 break;
4298 case 0x056: /* VIS I fpsub32 */
64a88d5d 4299 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4300 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
e9ebed4d
BS
4301 break;
4302 case 0x057: /* VIS I fpsub32s */
64a88d5d 4303 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4304 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
e9ebed4d 4305 break;
3299908c 4306 case 0x060: /* VIS I fzero */
64a88d5d 4307 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 4308 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
4309 tcg_gen_movi_i64(cpu_dst_64, 0);
4310 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4311 break;
4312 case 0x061: /* VIS I fzeros */
64a88d5d 4313 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 4314 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
4315 tcg_gen_movi_i32(cpu_dst_32, 0);
4316 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4317 break;
e9ebed4d 4318 case 0x062: /* VIS I fnor */
64a88d5d 4319 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4320 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
e9ebed4d
BS
4321 break;
4322 case 0x063: /* VIS I fnors */
64a88d5d 4323 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4324 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
e9ebed4d
BS
4325 break;
4326 case 0x064: /* VIS I fandnot2 */
64a88d5d 4327 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4328 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
e9ebed4d
BS
4329 break;
4330 case 0x065: /* VIS I fandnot2s */
64a88d5d 4331 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4332 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
e9ebed4d
BS
4333 break;
4334 case 0x066: /* VIS I fnot2 */
64a88d5d 4335 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4336 gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
e9ebed4d
BS
4337 break;
4338 case 0x067: /* VIS I fnot2s */
64a88d5d 4339 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4340 gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
e9ebed4d
BS
4341 break;
4342 case 0x068: /* VIS I fandnot1 */
64a88d5d 4343 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4344 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
e9ebed4d
BS
4345 break;
4346 case 0x069: /* VIS I fandnot1s */
64a88d5d 4347 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4348 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
e9ebed4d
BS
4349 break;
4350 case 0x06a: /* VIS I fnot1 */
64a88d5d 4351 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4352 gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
e9ebed4d
BS
4353 break;
4354 case 0x06b: /* VIS I fnot1s */
64a88d5d 4355 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4356 gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
e9ebed4d
BS
4357 break;
4358 case 0x06c: /* VIS I fxor */
64a88d5d 4359 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4360 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
e9ebed4d
BS
4361 break;
4362 case 0x06d: /* VIS I fxors */
64a88d5d 4363 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4364 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
e9ebed4d
BS
4365 break;
4366 case 0x06e: /* VIS I fnand */
64a88d5d 4367 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4368 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
e9ebed4d
BS
4369 break;
4370 case 0x06f: /* VIS I fnands */
64a88d5d 4371 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4372 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
e9ebed4d
BS
4373 break;
4374 case 0x070: /* VIS I fand */
64a88d5d 4375 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4376 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
e9ebed4d
BS
4377 break;
4378 case 0x071: /* VIS I fands */
64a88d5d 4379 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4380 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
e9ebed4d
BS
4381 break;
4382 case 0x072: /* VIS I fxnor */
64a88d5d 4383 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4384 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
e9ebed4d
BS
4385 break;
4386 case 0x073: /* VIS I fxnors */
64a88d5d 4387 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4388 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
e9ebed4d 4389 break;
3299908c 4390 case 0x074: /* VIS I fsrc1 */
64a88d5d 4391 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4392 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4393 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4394 break;
4395 case 0x075: /* VIS I fsrc1s */
64a88d5d 4396 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4397 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4398 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4399 break;
e9ebed4d 4400 case 0x076: /* VIS I fornot2 */
64a88d5d 4401 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4402 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
e9ebed4d
BS
4403 break;
4404 case 0x077: /* VIS I fornot2s */
64a88d5d 4405 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4406 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
e9ebed4d 4407 break;
3299908c 4408 case 0x078: /* VIS I fsrc2 */
64a88d5d 4409 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4410 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4411 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4412 break;
4413 case 0x079: /* VIS I fsrc2s */
64a88d5d 4414 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4415 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
4416 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4417 break;
e9ebed4d 4418 case 0x07a: /* VIS I fornot1 */
64a88d5d 4419 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4420 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
e9ebed4d
BS
4421 break;
4422 case 0x07b: /* VIS I fornot1s */
64a88d5d 4423 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4424 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
e9ebed4d
BS
4425 break;
4426 case 0x07c: /* VIS I for */
64a88d5d 4427 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4428 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
e9ebed4d
BS
4429 break;
4430 case 0x07d: /* VIS I fors */
64a88d5d 4431 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4432 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
e9ebed4d 4433 break;
3299908c 4434 case 0x07e: /* VIS I fone */
64a88d5d 4435 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 4436 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
4437 tcg_gen_movi_i64(cpu_dst_64, -1);
4438 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4439 break;
4440 case 0x07f: /* VIS I fones */
64a88d5d 4441 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 4442 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
4443 tcg_gen_movi_i32(cpu_dst_32, -1);
4444 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4445 break;
e9ebed4d
BS
4446 case 0x080: /* VIS I shutdown */
4447 case 0x081: /* VIS II siam */
4448 // XXX
4449 goto illegal_insn;
3299908c
BS
4450 default:
4451 goto illegal_insn;
4452 }
4453#else
0f8a249a 4454 goto ncp_insn;
3299908c
BS
4455#endif
4456 } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
fcc72045 4457#ifdef TARGET_SPARC64
0f8a249a 4458 goto illegal_insn;
fcc72045 4459#else
0f8a249a 4460 goto ncp_insn;
fcc72045 4461#endif
3475187d 4462#ifdef TARGET_SPARC64
0f8a249a 4463 } else if (xop == 0x39) { /* V9 return */
a7812ae4 4464 TCGv_i32 r_const;
2ea815ca 4465
66442b07 4466 save_state(dc);
9d1d4e34 4467 cpu_src1 = get_src1(dc, insn);
de9e9d9f 4468 cpu_tmp0 = get_temp_tl(dc);
0f8a249a 4469 if (IS_IMM) { /* immediate */
67526b20 4470 simm = GET_FIELDs(insn, 19, 31);
7b04bd5c 4471 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
0f8a249a 4472 } else { /* register */
3475187d 4473 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4474 if (rs2) {
97ea2859 4475 cpu_src2 = gen_load_gpr(dc, rs2);
7b04bd5c 4476 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
97ea2859 4477 } else {
7b04bd5c 4478 tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
97ea2859 4479 }
3475187d 4480 }
063c3675 4481 gen_helper_restore(cpu_env);
13a6dd00 4482 gen_mov_pc_npc(dc);
2ea815ca 4483 r_const = tcg_const_i32(3);
7b04bd5c 4484 gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
a7812ae4 4485 tcg_temp_free_i32(r_const);
7b04bd5c 4486 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a
BS
4487 dc->npc = DYNAMIC_PC;
4488 goto jmp_insn;
3475187d 4489#endif
0f8a249a 4490 } else {
9d1d4e34 4491 cpu_src1 = get_src1(dc, insn);
de9e9d9f 4492 cpu_tmp0 = get_temp_tl(dc);
0f8a249a 4493 if (IS_IMM) { /* immediate */
67526b20 4494 simm = GET_FIELDs(insn, 19, 31);
7b04bd5c 4495 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
0f8a249a 4496 } else { /* register */
e80cfcfc 4497 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4498 if (rs2) {
97ea2859 4499 cpu_src2 = gen_load_gpr(dc, rs2);
7b04bd5c 4500 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
97ea2859 4501 } else {
7b04bd5c 4502 tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
97ea2859 4503 }
cf495bcf 4504 }
0f8a249a
BS
4505 switch (xop) {
4506 case 0x38: /* jmpl */
4507 {
97ea2859 4508 TCGv t;
a7812ae4 4509 TCGv_i32 r_const;
2ea815ca 4510
97ea2859
RH
4511 t = gen_dest_gpr(dc, rd);
4512 tcg_gen_movi_tl(t, dc->pc);
4513 gen_store_gpr(dc, rd, t);
13a6dd00 4514 gen_mov_pc_npc(dc);
2ea815ca 4515 r_const = tcg_const_i32(3);
7b04bd5c 4516 gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
a7812ae4 4517 tcg_temp_free_i32(r_const);
7b04bd5c
RH
4518 gen_address_mask(dc, cpu_tmp0);
4519 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a
BS
4520 dc->npc = DYNAMIC_PC;
4521 }
4522 goto jmp_insn;
3475187d 4523#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
0f8a249a
BS
4524 case 0x39: /* rett, V9 return */
4525 {
a7812ae4 4526 TCGv_i32 r_const;
2ea815ca 4527
0f8a249a
BS
4528 if (!supervisor(dc))
4529 goto priv_insn;
13a6dd00 4530 gen_mov_pc_npc(dc);
2ea815ca 4531 r_const = tcg_const_i32(3);
7b04bd5c 4532 gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
a7812ae4 4533 tcg_temp_free_i32(r_const);
7b04bd5c 4534 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a 4535 dc->npc = DYNAMIC_PC;
063c3675 4536 gen_helper_rett(cpu_env);
0f8a249a
BS
4537 }
4538 goto jmp_insn;
4539#endif
4540 case 0x3b: /* flush */
5578ceab 4541 if (!((dc)->def->features & CPU_FEATURE_FLUSH))
64a88d5d 4542 goto unimp_flush;
dcfd14b3 4543 /* nop */
0f8a249a
BS
4544 break;
4545 case 0x3c: /* save */
66442b07 4546 save_state(dc);
063c3675 4547 gen_helper_save(cpu_env);
7b04bd5c 4548 gen_store_gpr(dc, rd, cpu_tmp0);
0f8a249a
BS
4549 break;
4550 case 0x3d: /* restore */
66442b07 4551 save_state(dc);
063c3675 4552 gen_helper_restore(cpu_env);
7b04bd5c 4553 gen_store_gpr(dc, rd, cpu_tmp0);
0f8a249a 4554 break;
3475187d 4555#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
0f8a249a
BS
4556 case 0x3e: /* V9 done/retry */
4557 {
4558 switch (rd) {
4559 case 0:
4560 if (!supervisor(dc))
4561 goto priv_insn;
4562 dc->npc = DYNAMIC_PC;
4563 dc->pc = DYNAMIC_PC;
063c3675 4564 gen_helper_done(cpu_env);
0f8a249a
BS
4565 goto jmp_insn;
4566 case 1:
4567 if (!supervisor(dc))
4568 goto priv_insn;
4569 dc->npc = DYNAMIC_PC;
4570 dc->pc = DYNAMIC_PC;
063c3675 4571 gen_helper_retry(cpu_env);
0f8a249a
BS
4572 goto jmp_insn;
4573 default:
4574 goto illegal_insn;
4575 }
4576 }
4577 break;
4578#endif
4579 default:
4580 goto illegal_insn;
4581 }
cf495bcf 4582 }
0f8a249a
BS
4583 break;
4584 }
4585 break;
4586 case 3: /* load/store instructions */
4587 {
4588 unsigned int xop = GET_FIELD(insn, 7, 12);
5e6ed439
RH
4589 /* ??? gen_address_mask prevents us from using a source
4590 register directly. Always generate a temporary. */
4591 TCGv cpu_addr = get_temp_tl(dc);
9322a4bf 4592
5e6ed439
RH
4593 tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn));
4594 if (xop == 0x3c || xop == 0x3e) {
4595 /* V9 casa/casxa : no offset */
71817e48 4596 } else if (IS_IMM) { /* immediate */
67526b20 4597 simm = GET_FIELDs(insn, 19, 31);
5e6ed439
RH
4598 if (simm != 0) {
4599 tcg_gen_addi_tl(cpu_addr, cpu_addr, simm);
4600 }
0f8a249a
BS
4601 } else { /* register */
4602 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4603 if (rs2 != 0) {
5e6ed439 4604 tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2));
97ea2859 4605 }
0f8a249a 4606 }
2f2ecb83
BS
4607 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
4608 (xop > 0x17 && xop <= 0x1d ) ||
4609 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
81634eea
RH
4610 TCGv cpu_val = gen_dest_gpr(dc, rd);
4611
0f8a249a 4612 switch (xop) {
b89e94af 4613 case 0x0: /* ld, V9 lduw, load unsigned word */
2cade6a3 4614 gen_address_mask(dc, cpu_addr);
6ae20372 4615 tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4616 break;
b89e94af 4617 case 0x1: /* ldub, load unsigned byte */
2cade6a3 4618 gen_address_mask(dc, cpu_addr);
6ae20372 4619 tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4620 break;
b89e94af 4621 case 0x2: /* lduh, load unsigned halfword */
2cade6a3 4622 gen_address_mask(dc, cpu_addr);
6ae20372 4623 tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4624 break;
b89e94af 4625 case 0x3: /* ldd, load double word */
0f8a249a 4626 if (rd & 1)
d4218d99 4627 goto illegal_insn;
1a2fb1c0 4628 else {
a7812ae4 4629 TCGv_i32 r_const;
abcc7191 4630 TCGv_i64 t64;
2ea815ca 4631
66442b07 4632 save_state(dc);
2ea815ca 4633 r_const = tcg_const_i32(7);
fe8d8f0f
BS
4634 /* XXX remove alignment check */
4635 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 4636 tcg_temp_free_i32(r_const);
2cade6a3 4637 gen_address_mask(dc, cpu_addr);
abcc7191
RH
4638 t64 = tcg_temp_new_i64();
4639 tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
de9e9d9f
RH
4640 tcg_gen_trunc_i64_tl(cpu_val, t64);
4641 tcg_gen_ext32u_tl(cpu_val, cpu_val);
4642 gen_store_gpr(dc, rd + 1, cpu_val);
abcc7191
RH
4643 tcg_gen_shri_i64(t64, t64, 32);
4644 tcg_gen_trunc_i64_tl(cpu_val, t64);
4645 tcg_temp_free_i64(t64);
de9e9d9f 4646 tcg_gen_ext32u_tl(cpu_val, cpu_val);
1a2fb1c0 4647 }
0f8a249a 4648 break;
b89e94af 4649 case 0x9: /* ldsb, load signed byte */
2cade6a3 4650 gen_address_mask(dc, cpu_addr);
6ae20372 4651 tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4652 break;
b89e94af 4653 case 0xa: /* ldsh, load signed halfword */
2cade6a3 4654 gen_address_mask(dc, cpu_addr);
6ae20372 4655 tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4656 break;
4657 case 0xd: /* ldstub -- XXX: should be atomically */
2ea815ca
BS
4658 {
4659 TCGv r_const;
b64d2e57 4660 TCGv tmp = tcg_temp_new();
2ea815ca 4661
2cade6a3 4662 gen_address_mask(dc, cpu_addr);
b64d2e57 4663 tcg_gen_qemu_ld8u(tmp, cpu_addr, dc->mem_idx);
2ea815ca
BS
4664 r_const = tcg_const_tl(0xff);
4665 tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
b64d2e57 4666 tcg_gen_mov_tl(cpu_val, tmp);
2ea815ca 4667 tcg_temp_free(r_const);
b64d2e57 4668 tcg_temp_free(tmp);
2ea815ca 4669 }
0f8a249a 4670 break;
de9e9d9f
RH
4671 case 0x0f:
4672 /* swap, swap register with memory. Also atomically */
4673 {
4674 TCGv t0 = get_temp_tl(dc);
4675 CHECK_IU_FEATURE(dc, SWAP);
4676 cpu_src1 = gen_load_gpr(dc, rd);
4677 gen_address_mask(dc, cpu_addr);
4678 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
4679 tcg_gen_qemu_st32(cpu_src1, cpu_addr, dc->mem_idx);
4680 tcg_gen_mov_tl(cpu_val, t0);
4681 }
0f8a249a 4682 break;
3475187d 4683#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 4684 case 0x10: /* lda, V9 lduwa, load word alternate */
3475187d 4685#ifndef TARGET_SPARC64
0f8a249a
BS
4686 if (IS_IMM)
4687 goto illegal_insn;
4688 if (!supervisor(dc))
4689 goto priv_insn;
6ea4a6c8 4690#endif
66442b07 4691 save_state(dc);
22e70060 4692 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 0);
0f8a249a 4693 break;
b89e94af 4694 case 0x11: /* lduba, load unsigned byte alternate */
3475187d 4695#ifndef TARGET_SPARC64
0f8a249a
BS
4696 if (IS_IMM)
4697 goto illegal_insn;
4698 if (!supervisor(dc))
4699 goto priv_insn;
4700#endif
66442b07 4701 save_state(dc);
22e70060 4702 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 0);
0f8a249a 4703 break;
b89e94af 4704 case 0x12: /* lduha, load unsigned halfword alternate */
3475187d 4705#ifndef TARGET_SPARC64
0f8a249a
BS
4706 if (IS_IMM)
4707 goto illegal_insn;
4708 if (!supervisor(dc))
4709 goto priv_insn;
3475187d 4710#endif
66442b07 4711 save_state(dc);
22e70060 4712 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 0);
0f8a249a 4713 break;
b89e94af 4714 case 0x13: /* ldda, load double word alternate */
3475187d 4715#ifndef TARGET_SPARC64
0f8a249a
BS
4716 if (IS_IMM)
4717 goto illegal_insn;
4718 if (!supervisor(dc))
4719 goto priv_insn;
3475187d 4720#endif
0f8a249a 4721 if (rd & 1)
d4218d99 4722 goto illegal_insn;
66442b07 4723 save_state(dc);
c7785e16 4724 gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd);
db166940 4725 goto skip_move;
b89e94af 4726 case 0x19: /* ldsba, load signed byte alternate */
3475187d 4727#ifndef TARGET_SPARC64
0f8a249a
BS
4728 if (IS_IMM)
4729 goto illegal_insn;
4730 if (!supervisor(dc))
4731 goto priv_insn;
4732#endif
66442b07 4733 save_state(dc);
22e70060 4734 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 1);
0f8a249a 4735 break;
b89e94af 4736 case 0x1a: /* ldsha, load signed halfword alternate */
3475187d 4737#ifndef TARGET_SPARC64
0f8a249a
BS
4738 if (IS_IMM)
4739 goto illegal_insn;
4740 if (!supervisor(dc))
4741 goto priv_insn;
3475187d 4742#endif
66442b07 4743 save_state(dc);
22e70060 4744 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 1);
0f8a249a
BS
4745 break;
4746 case 0x1d: /* ldstuba -- XXX: should be atomically */
3475187d 4747#ifndef TARGET_SPARC64
0f8a249a
BS
4748 if (IS_IMM)
4749 goto illegal_insn;
4750 if (!supervisor(dc))
4751 goto priv_insn;
4752#endif
66442b07 4753 save_state(dc);
22e70060 4754 gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
0f8a249a 4755 break;
b89e94af 4756 case 0x1f: /* swapa, swap reg with alt. memory. Also
77f193da 4757 atomically */
64a88d5d 4758 CHECK_IU_FEATURE(dc, SWAP);
3475187d 4759#ifndef TARGET_SPARC64
0f8a249a
BS
4760 if (IS_IMM)
4761 goto illegal_insn;
4762 if (!supervisor(dc))
4763 goto priv_insn;
6ea4a6c8 4764#endif
66442b07 4765 save_state(dc);
06828032 4766 cpu_src1 = gen_load_gpr(dc, rd);
22e70060 4767 gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn);
0f8a249a 4768 break;
3475187d
FB
4769
4770#ifndef TARGET_SPARC64
0f8a249a
BS
4771 case 0x30: /* ldc */
4772 case 0x31: /* ldcsr */
4773 case 0x33: /* lddc */
4774 goto ncp_insn;
3475187d
FB
4775#endif
4776#endif
4777#ifdef TARGET_SPARC64
0f8a249a 4778 case 0x08: /* V9 ldsw */
2cade6a3 4779 gen_address_mask(dc, cpu_addr);
6ae20372 4780 tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4781 break;
4782 case 0x0b: /* V9 ldx */
2cade6a3 4783 gen_address_mask(dc, cpu_addr);
6ae20372 4784 tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4785 break;
4786 case 0x18: /* V9 ldswa */
66442b07 4787 save_state(dc);
22e70060 4788 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 1);
0f8a249a
BS
4789 break;
4790 case 0x1b: /* V9 ldxa */
66442b07 4791 save_state(dc);
22e70060 4792 gen_ld_asi(dc, cpu_val, cpu_addr, insn, 8, 0);
0f8a249a
BS
4793 break;
4794 case 0x2d: /* V9 prefetch, no effect */
4795 goto skip_move;
4796 case 0x30: /* V9 ldfa */
5b12f1e8 4797 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4798 goto jmp_insn;
4799 }
66442b07 4800 save_state(dc);
22e70060 4801 gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
638737ad 4802 gen_update_fprs_dirty(rd);
81ad8ba2 4803 goto skip_move;
0f8a249a 4804 case 0x33: /* V9 lddfa */
5b12f1e8 4805 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4806 goto jmp_insn;
4807 }
66442b07 4808 save_state(dc);
22e70060 4809 gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
638737ad 4810 gen_update_fprs_dirty(DFPREG(rd));
81ad8ba2 4811 goto skip_move;
0f8a249a
BS
4812 case 0x3d: /* V9 prefetcha, no effect */
4813 goto skip_move;
4814 case 0x32: /* V9 ldqfa */
64a88d5d 4815 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 4816 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4817 goto jmp_insn;
4818 }
66442b07 4819 save_state(dc);
22e70060 4820 gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
638737ad 4821 gen_update_fprs_dirty(QFPREG(rd));
1f587329 4822 goto skip_move;
0f8a249a
BS
4823#endif
4824 default:
4825 goto illegal_insn;
4826 }
97ea2859 4827 gen_store_gpr(dc, rd, cpu_val);
db166940 4828#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 4829 skip_move: ;
3475187d 4830#endif
0f8a249a 4831 } else if (xop >= 0x20 && xop < 0x24) {
de9e9d9f
RH
4832 TCGv t0;
4833
5b12f1e8 4834 if (gen_trap_ifnofpu(dc)) {
a80dde08 4835 goto jmp_insn;
5b12f1e8 4836 }
66442b07 4837 save_state(dc);
0f8a249a 4838 switch (xop) {
b89e94af 4839 case 0x20: /* ldf, load fpreg */
2cade6a3 4840 gen_address_mask(dc, cpu_addr);
de9e9d9f
RH
4841 t0 = get_temp_tl(dc);
4842 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
ba5f5179 4843 cpu_dst_32 = gen_dest_fpr_F(dc);
de9e9d9f 4844 tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
208ae657 4845 gen_store_fpr_F(dc, rd, cpu_dst_32);
0f8a249a 4846 break;
3a3b925d
BS
4847 case 0x21: /* ldfsr, V9 ldxfsr */
4848#ifdef TARGET_SPARC64
2cade6a3 4849 gen_address_mask(dc, cpu_addr);
3a3b925d 4850 if (rd == 1) {
abcc7191
RH
4851 TCGv_i64 t64 = tcg_temp_new_i64();
4852 tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
4853 gen_helper_ldxfsr(cpu_env, t64);
4854 tcg_temp_free_i64(t64);
f8641947 4855 break;
fe987e23 4856 }
f8641947 4857#endif
de9e9d9f
RH
4858 cpu_dst_32 = get_temp_i32(dc);
4859 t0 = get_temp_tl(dc);
4860 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
4861 tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
4862 gen_helper_ldfsr(cpu_env, cpu_dst_32);
0f8a249a 4863 break;
b89e94af 4864 case 0x22: /* ldqf, load quad fpreg */
2ea815ca 4865 {
a7812ae4 4866 TCGv_i32 r_const;
2ea815ca
BS
4867
4868 CHECK_FPU_FEATURE(dc, FLOAT128);
4869 r_const = tcg_const_i32(dc->mem_idx);
1295001c 4870 gen_address_mask(dc, cpu_addr);
fe8d8f0f 4871 gen_helper_ldqf(cpu_env, cpu_addr, r_const);
a7812ae4 4872 tcg_temp_free_i32(r_const);
2ea815ca 4873 gen_op_store_QT0_fpr(QFPREG(rd));
638737ad 4874 gen_update_fprs_dirty(QFPREG(rd));
2ea815ca 4875 }
1f587329 4876 break;
b89e94af 4877 case 0x23: /* lddf, load double fpreg */
03fb8cfc 4878 gen_address_mask(dc, cpu_addr);
3886b8a3 4879 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
03fb8cfc
RH
4880 tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx);
4881 gen_store_fpr_D(dc, rd, cpu_dst_64);
0f8a249a
BS
4882 break;
4883 default:
4884 goto illegal_insn;
4885 }
dc1a6971 4886 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
0f8a249a 4887 xop == 0xe || xop == 0x1e) {
81634eea
RH
4888 TCGv cpu_val = gen_load_gpr(dc, rd);
4889
0f8a249a 4890 switch (xop) {
b89e94af 4891 case 0x4: /* st, store word */
2cade6a3 4892 gen_address_mask(dc, cpu_addr);
6ae20372 4893 tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4894 break;
b89e94af 4895 case 0x5: /* stb, store byte */
2cade6a3 4896 gen_address_mask(dc, cpu_addr);
6ae20372 4897 tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4898 break;
b89e94af 4899 case 0x6: /* sth, store halfword */
2cade6a3 4900 gen_address_mask(dc, cpu_addr);
6ae20372 4901 tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4902 break;
b89e94af 4903 case 0x7: /* std, store double word */
0f8a249a 4904 if (rd & 1)
d4218d99 4905 goto illegal_insn;
1a2fb1c0 4906 else {
a7812ae4 4907 TCGv_i32 r_const;
abcc7191 4908 TCGv_i64 t64;
81634eea 4909 TCGv lo;
1a2fb1c0 4910
66442b07 4911 save_state(dc);
2cade6a3 4912 gen_address_mask(dc, cpu_addr);
2ea815ca 4913 r_const = tcg_const_i32(7);
fe8d8f0f
BS
4914 /* XXX remove alignment check */
4915 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 4916 tcg_temp_free_i32(r_const);
81634eea 4917 lo = gen_load_gpr(dc, rd + 1);
abcc7191
RH
4918
4919 t64 = tcg_temp_new_i64();
4920 tcg_gen_concat_tl_i64(t64, lo, cpu_val);
4921 tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx);
4922 tcg_temp_free_i64(t64);
7fa76c0b 4923 }
0f8a249a 4924 break;
3475187d 4925#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 4926 case 0x14: /* sta, V9 stwa, store word alternate */
3475187d 4927#ifndef TARGET_SPARC64
0f8a249a
BS
4928 if (IS_IMM)
4929 goto illegal_insn;
4930 if (!supervisor(dc))
4931 goto priv_insn;
6ea4a6c8 4932#endif
66442b07 4933 save_state(dc);
22e70060 4934 gen_st_asi(dc, cpu_val, cpu_addr, insn, 4);
9fd1ae3a 4935 dc->npc = DYNAMIC_PC;
d39c0b99 4936 break;
b89e94af 4937 case 0x15: /* stba, store byte alternate */
3475187d 4938#ifndef TARGET_SPARC64
0f8a249a
BS
4939 if (IS_IMM)
4940 goto illegal_insn;
4941 if (!supervisor(dc))
4942 goto priv_insn;
3475187d 4943#endif
66442b07 4944 save_state(dc);
22e70060 4945 gen_st_asi(dc, cpu_val, cpu_addr, insn, 1);
9fd1ae3a 4946 dc->npc = DYNAMIC_PC;
d39c0b99 4947 break;
b89e94af 4948 case 0x16: /* stha, store halfword alternate */
3475187d 4949#ifndef TARGET_SPARC64
0f8a249a
BS
4950 if (IS_IMM)
4951 goto illegal_insn;
4952 if (!supervisor(dc))
4953 goto priv_insn;
6ea4a6c8 4954#endif
66442b07 4955 save_state(dc);
22e70060 4956 gen_st_asi(dc, cpu_val, cpu_addr, insn, 2);
9fd1ae3a 4957 dc->npc = DYNAMIC_PC;
d39c0b99 4958 break;
b89e94af 4959 case 0x17: /* stda, store double word alternate */
3475187d 4960#ifndef TARGET_SPARC64
0f8a249a
BS
4961 if (IS_IMM)
4962 goto illegal_insn;
4963 if (!supervisor(dc))
4964 goto priv_insn;
3475187d 4965#endif
0f8a249a 4966 if (rd & 1)
d4218d99 4967 goto illegal_insn;
1a2fb1c0 4968 else {
66442b07 4969 save_state(dc);
c7785e16 4970 gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
1a2fb1c0 4971 }
d39c0b99 4972 break;
e80cfcfc 4973#endif
3475187d 4974#ifdef TARGET_SPARC64
0f8a249a 4975 case 0x0e: /* V9 stx */
2cade6a3 4976 gen_address_mask(dc, cpu_addr);
6ae20372 4977 tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4978 break;
4979 case 0x1e: /* V9 stxa */
66442b07 4980 save_state(dc);
22e70060 4981 gen_st_asi(dc, cpu_val, cpu_addr, insn, 8);
9fd1ae3a 4982 dc->npc = DYNAMIC_PC;
0f8a249a 4983 break;
3475187d 4984#endif
0f8a249a
BS
4985 default:
4986 goto illegal_insn;
4987 }
4988 } else if (xop > 0x23 && xop < 0x28) {
5b12f1e8 4989 if (gen_trap_ifnofpu(dc)) {
a80dde08 4990 goto jmp_insn;
5b12f1e8 4991 }
66442b07 4992 save_state(dc);
0f8a249a 4993 switch (xop) {
b89e94af 4994 case 0x24: /* stf, store fpreg */
de9e9d9f
RH
4995 {
4996 TCGv t = get_temp_tl(dc);
4997 gen_address_mask(dc, cpu_addr);
4998 cpu_src1_32 = gen_load_fpr_F(dc, rd);
4999 tcg_gen_ext_i32_tl(t, cpu_src1_32);
5000 tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx);
5001 }
0f8a249a
BS
5002 break;
5003 case 0x25: /* stfsr, V9 stxfsr */
f8641947
RH
5004 {
5005 TCGv t = get_temp_tl(dc);
5006
5007 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUSPARCState, fsr));
3a3b925d 5008#ifdef TARGET_SPARC64
f8641947
RH
5009 gen_address_mask(dc, cpu_addr);
5010 if (rd == 1) {
5011 tcg_gen_qemu_st64(t, cpu_addr, dc->mem_idx);
5012 break;
5013 }
3a3b925d 5014#endif
f8641947
RH
5015 tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx);
5016 }
0f8a249a 5017 break;
1f587329
BS
5018 case 0x26:
5019#ifdef TARGET_SPARC64
1f587329 5020 /* V9 stqf, store quad fpreg */
2ea815ca 5021 {
a7812ae4 5022 TCGv_i32 r_const;
2ea815ca
BS
5023
5024 CHECK_FPU_FEATURE(dc, FLOAT128);
5025 gen_op_load_fpr_QT0(QFPREG(rd));
5026 r_const = tcg_const_i32(dc->mem_idx);
1295001c 5027 gen_address_mask(dc, cpu_addr);
fe8d8f0f 5028 gen_helper_stqf(cpu_env, cpu_addr, r_const);
a7812ae4 5029 tcg_temp_free_i32(r_const);
2ea815ca 5030 }
1f587329 5031 break;
1f587329
BS
5032#else /* !TARGET_SPARC64 */
5033 /* stdfq, store floating point queue */
5034#if defined(CONFIG_USER_ONLY)
5035 goto illegal_insn;
5036#else
0f8a249a
BS
5037 if (!supervisor(dc))
5038 goto priv_insn;
5b12f1e8 5039 if (gen_trap_ifnofpu(dc)) {
0f8a249a 5040 goto jmp_insn;
5b12f1e8 5041 }
0f8a249a 5042 goto nfq_insn;
1f587329 5043#endif
0f8a249a 5044#endif
b89e94af 5045 case 0x27: /* stdf, store double fpreg */
03fb8cfc
RH
5046 gen_address_mask(dc, cpu_addr);
5047 cpu_src1_64 = gen_load_fpr_D(dc, rd);
5048 tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx);
0f8a249a
BS
5049 break;
5050 default:
5051 goto illegal_insn;
5052 }
5053 } else if (xop > 0x33 && xop < 0x3f) {
66442b07 5054 save_state(dc);
0f8a249a 5055 switch (xop) {
a4d17f19 5056#ifdef TARGET_SPARC64
0f8a249a 5057 case 0x34: /* V9 stfa */
5b12f1e8 5058 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5059 goto jmp_insn;
5060 }
22e70060 5061 gen_stf_asi(dc, cpu_addr, insn, 4, rd);
0f8a249a 5062 break;
1f587329 5063 case 0x36: /* V9 stqfa */
2ea815ca 5064 {
a7812ae4 5065 TCGv_i32 r_const;
2ea815ca
BS
5066
5067 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5068 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5069 goto jmp_insn;
5070 }
2ea815ca 5071 r_const = tcg_const_i32(7);
fe8d8f0f 5072 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 5073 tcg_temp_free_i32(r_const);
22e70060 5074 gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
2ea815ca 5075 }
1f587329 5076 break;
0f8a249a 5077 case 0x37: /* V9 stdfa */
5b12f1e8 5078 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5079 goto jmp_insn;
5080 }
22e70060 5081 gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
0f8a249a 5082 break;
0f8a249a 5083 case 0x3e: /* V9 casxa */
a4273524
RH
5084 rs2 = GET_FIELD(insn, 27, 31);
5085 cpu_src2 = gen_load_gpr(dc, rs2);
81634eea 5086 gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd);
0f8a249a 5087 break;
a4d17f19 5088#else
0f8a249a
BS
5089 case 0x34: /* stc */
5090 case 0x35: /* stcsr */
5091 case 0x36: /* stdcq */
5092 case 0x37: /* stdc */
5093 goto ncp_insn;
16c358e9
SH
5094#endif
5095#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5096 case 0x3c: /* V9 or LEON3 casa */
5097#ifndef TARGET_SPARC64
5098 CHECK_IU_FEATURE(dc, CASA);
5099 if (IS_IMM) {
5100 goto illegal_insn;
5101 }
bd4e097a
AZ
5102 /* LEON3 allows CASA from user space with ASI 0xa */
5103 if ((GET_FIELD(insn, 19, 26) != 0xa) && !supervisor(dc)) {
16c358e9
SH
5104 goto priv_insn;
5105 }
5106#endif
5107 rs2 = GET_FIELD(insn, 27, 31);
5108 cpu_src2 = gen_load_gpr(dc, rs2);
5109 gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
5110 break;
0f8a249a
BS
5111#endif
5112 default:
5113 goto illegal_insn;
5114 }
a4273524 5115 } else {
0f8a249a 5116 goto illegal_insn;
a4273524 5117 }
0f8a249a
BS
5118 }
5119 break;
cf495bcf
FB
5120 }
5121 /* default case for non jump instructions */
72cbca10 5122 if (dc->npc == DYNAMIC_PC) {
0f8a249a
BS
5123 dc->pc = DYNAMIC_PC;
5124 gen_op_next_insn();
72cbca10
FB
5125 } else if (dc->npc == JUMP_PC) {
5126 /* we can do a static jump */
6ae20372 5127 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
72cbca10
FB
5128 dc->is_br = 1;
5129 } else {
0f8a249a
BS
5130 dc->pc = dc->npc;
5131 dc->npc = dc->npc + 4;
cf495bcf 5132 }
e80cfcfc 5133 jmp_insn:
42a8aa83 5134 goto egress;
cf495bcf 5135 illegal_insn:
4fbe0067 5136 gen_exception(dc, TT_ILL_INSN);
42a8aa83 5137 goto egress;
64a88d5d 5138 unimp_flush:
4fbe0067 5139 gen_exception(dc, TT_UNIMP_FLUSH);
42a8aa83 5140 goto egress;
e80cfcfc 5141#if !defined(CONFIG_USER_ONLY)
e8af50a3 5142 priv_insn:
4fbe0067 5143 gen_exception(dc, TT_PRIV_INSN);
42a8aa83 5144 goto egress;
64a88d5d 5145#endif
e80cfcfc 5146 nfpu_insn:
4fbe0067 5147 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
42a8aa83 5148 goto egress;
64a88d5d 5149#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
9143e598 5150 nfq_insn:
4fbe0067 5151 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
42a8aa83 5152 goto egress;
9143e598 5153#endif
fcc72045
BS
5154#ifndef TARGET_SPARC64
5155 ncp_insn:
4fbe0067 5156 gen_exception(dc, TT_NCP_INSN);
42a8aa83 5157 goto egress;
fcc72045 5158#endif
42a8aa83 5159 egress:
30038fd8
RH
5160 if (dc->n_t32 != 0) {
5161 int i;
5162 for (i = dc->n_t32 - 1; i >= 0; --i) {
5163 tcg_temp_free_i32(dc->t32[i]);
5164 }
5165 dc->n_t32 = 0;
5166 }
88023616
RH
5167 if (dc->n_ttl != 0) {
5168 int i;
5169 for (i = dc->n_ttl - 1; i >= 0; --i) {
5170 tcg_temp_free(dc->ttl[i]);
5171 }
5172 dc->n_ttl = 0;
5173 }
7a3f1944
FB
5174}
5175
4e5e1215 5176void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 5177{
4e5e1215 5178 SPARCCPU *cpu = sparc_env_get_cpu(env);
ed2803da 5179 CPUState *cs = CPU(cpu);
72cbca10 5180 target_ulong pc_start, last_pc;
cf495bcf 5181 DisasContext dc1, *dc = &dc1;
2e70f6ef
PB
5182 int num_insns;
5183 int max_insns;
0184e266 5184 unsigned int insn;
cf495bcf
FB
5185
5186 memset(dc, 0, sizeof(DisasContext));
cf495bcf 5187 dc->tb = tb;
72cbca10 5188 pc_start = tb->pc;
cf495bcf 5189 dc->pc = pc_start;
e80cfcfc 5190 last_pc = dc->pc;
72cbca10 5191 dc->npc = (target_ulong) tb->cs_base;
8393617c 5192 dc->cc_op = CC_OP_DYNAMIC;
99a23063 5193 dc->mem_idx = tb->flags & TB_FLAG_MMU_MASK;
5578ceab 5194 dc->def = env->def;
f838e2c5
BS
5195 dc->fpu_enabled = tb_fpu_enabled(tb->flags);
5196 dc->address_mask_32bit = tb_am_enabled(tb->flags);
ed2803da 5197 dc->singlestep = (cs->singlestep_enabled || singlestep);
cf495bcf 5198
2e70f6ef
PB
5199 num_insns = 0;
5200 max_insns = tb->cflags & CF_COUNT_MASK;
190ce7fb 5201 if (max_insns == 0) {
2e70f6ef 5202 max_insns = CF_COUNT_MASK;
190ce7fb
RH
5203 }
5204 if (max_insns > TCG_MAX_INSNS) {
5205 max_insns = TCG_MAX_INSNS;
5206 }
5207
cd42d5b2 5208 gen_tb_start(tb);
cf495bcf 5209 do {
a3d5ad76
RH
5210 if (dc->npc & JUMP_PC) {
5211 assert(dc->jump_pc[1] == dc->pc + 4);
5212 tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC);
5213 } else {
5214 tcg_gen_insn_start(dc->pc, dc->npc);
5215 }
959082fc 5216 num_insns++;
522a0d4e 5217 last_pc = dc->pc;
667b8e29 5218
b933066a
RH
5219 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
5220 if (dc->pc != pc_start) {
5221 save_state(dc);
5222 }
5223 gen_helper_debug(cpu_env);
5224 tcg_gen_exit_tb(0);
5225 dc->is_br = 1;
5226 goto exit_gen_loop;
5227 }
5228
959082fc 5229 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
2e70f6ef 5230 gen_io_start();
667b8e29
RH
5231 }
5232
0184e266 5233 insn = cpu_ldl_code(env, dc->pc);
b09b2fd3 5234
0184e266 5235 disas_sparc_insn(dc, insn);
0f8a249a
BS
5236
5237 if (dc->is_br)
5238 break;
5239 /* if the next PC is different, we abort now */
5240 if (dc->pc != (last_pc + 4))
5241 break;
d39c0b99
FB
5242 /* if we reach a page boundary, we stop generation so that the
5243 PC of a TT_TFAULT exception is always in the right page */
5244 if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
5245 break;
e80cfcfc
FB
5246 /* if single step mode, we generate only one instruction and
5247 generate an exception */
060718c1 5248 if (dc->singlestep) {
e80cfcfc
FB
5249 break;
5250 }
fe700adb 5251 } while (!tcg_op_buf_full() &&
2e70f6ef
PB
5252 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
5253 num_insns < max_insns);
e80cfcfc
FB
5254
5255 exit_gen_loop:
b09b2fd3 5256 if (tb->cflags & CF_LAST_IO) {
2e70f6ef 5257 gen_io_end();
b09b2fd3 5258 }
72cbca10 5259 if (!dc->is_br) {
5fafdf24 5260 if (dc->pc != DYNAMIC_PC &&
72cbca10
FB
5261 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
5262 /* static PC and NPC: we can use direct chaining */
2f5680ee 5263 gen_goto_tb(dc, 0, dc->pc, dc->npc);
72cbca10 5264 } else {
b09b2fd3 5265 if (dc->pc != DYNAMIC_PC) {
2f5680ee 5266 tcg_gen_movi_tl(cpu_pc, dc->pc);
b09b2fd3 5267 }
934da7ee 5268 save_npc(dc);
57fec1fe 5269 tcg_gen_exit_tb(0);
72cbca10
FB
5270 }
5271 }
806f352d 5272 gen_tb_end(tb, num_insns);
0a7df5da 5273
4e5e1215
RH
5274 tb->size = last_pc + 4 - pc_start;
5275 tb->icount = num_insns;
5276
7a3f1944 5277#ifdef DEBUG_DISAS
4910e6e4
RH
5278 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
5279 && qemu_log_in_addr_range(pc_start)) {
93fcfe39
AL
5280 qemu_log("--------------\n");
5281 qemu_log("IN: %s\n", lookup_symbol(pc_start));
d49190c4 5282 log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0);
93fcfe39 5283 qemu_log("\n");
cf495bcf 5284 }
7a3f1944 5285#endif
7a3f1944
FB
5286}
5287
c48fcb47 5288void gen_intermediate_code_init(CPUSPARCState *env)
e80cfcfc 5289{
c48fcb47 5290 static int inited;
d2dc4069 5291 static const char gregnames[32][4] = {
0ea63844 5292 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
d2dc4069
RH
5293 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5294 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5295 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
f5069b26 5296 };
0ea63844 5297 static const char fregnames[32][4] = {
30038fd8
RH
5298 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5299 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5300 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5301 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
714547bb 5302 };
aaed909a 5303
0ea63844 5304 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
1a2fb1c0 5305#ifdef TARGET_SPARC64
0ea63844
RH
5306 { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
5307 { &cpu_asi, offsetof(CPUSPARCState, asi), "asi" },
5308 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
255e1fcb 5309#else
0ea63844
RH
5310 { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" },
5311#endif
5312 { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" },
5313 { &cpu_psr, offsetof(CPUSPARCState, psr), "psr" },
5314 };
5315
5316 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5317#ifdef TARGET_SPARC64
5318 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
5319 { &cpu_tick_cmpr, offsetof(CPUSPARCState, tick_cmpr), "tick_cmpr" },
5320 { &cpu_stick_cmpr, offsetof(CPUSPARCState, stick_cmpr), "stick_cmpr" },
5321 { &cpu_hstick_cmpr, offsetof(CPUSPARCState, hstick_cmpr),
5322 "hstick_cmpr" },
5323 { &cpu_hintp, offsetof(CPUSPARCState, hintp), "hintp" },
5324 { &cpu_htba, offsetof(CPUSPARCState, htba), "htba" },
5325 { &cpu_hver, offsetof(CPUSPARCState, hver), "hver" },
5326 { &cpu_ssr, offsetof(CPUSPARCState, ssr), "ssr" },
5327 { &cpu_ver, offsetof(CPUSPARCState, version), "ver" },
1a2fb1c0 5328#endif
0ea63844
RH
5329 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5330 { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" },
5331 { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" },
5332 { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" },
5333 { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
5334 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5335 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5336 { &cpu_y, offsetof(CPUSPARCState, y), "y" },
255e1fcb 5337#ifndef CONFIG_USER_ONLY
0ea63844 5338 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
255e1fcb 5339#endif
0ea63844
RH
5340 };
5341
5342 unsigned int i;
5343
5344 /* init various static tables */
5345 if (inited) {
5346 return;
5347 }
5348 inited = 1;
5349
5350 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7c255043 5351 tcg_ctx.tcg_env = cpu_env;
0ea63844
RH
5352
5353 cpu_regwptr = tcg_global_mem_new_ptr(cpu_env,
5354 offsetof(CPUSPARCState, regwptr),
5355 "regwptr");
5356
5357 for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5358 *r32[i].ptr = tcg_global_mem_new_i32(cpu_env, r32[i].off, r32[i].name);
5359 }
5360
5361 for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5362 *rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
5363 }
5364
d2dc4069 5365 TCGV_UNUSED(cpu_regs[0]);
0ea63844 5366 for (i = 1; i < 8; ++i) {
d2dc4069
RH
5367 cpu_regs[i] = tcg_global_mem_new(cpu_env,
5368 offsetof(CPUSPARCState, gregs[i]),
5369 gregnames[i]);
5370 }
5371
5372 for (i = 8; i < 32; ++i) {
5373 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5374 (i - 8) * sizeof(target_ulong),
5375 gregnames[i]);
0ea63844
RH
5376 }
5377
5378 for (i = 0; i < TARGET_DPREGS; i++) {
5379 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
5380 offsetof(CPUSPARCState, fpr[i]),
5381 fregnames[i]);
1a2fb1c0 5382 }
658138bc 5383}
d2856f1a 5384
bad729e2
RH
5385void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb,
5386 target_ulong *data)
d2856f1a 5387{
bad729e2
RH
5388 target_ulong pc = data[0];
5389 target_ulong npc = data[1];
5390
5391 env->pc = pc;
6c42444f 5392 if (npc == DYNAMIC_PC) {
d2856f1a 5393 /* dynamic NPC: already stored */
6c42444f 5394 } else if (npc & JUMP_PC) {
d7da2a10
BS
5395 /* jump PC: use 'cond' and the jump targets of the translation */
5396 if (env->cond) {
6c42444f 5397 env->npc = npc & ~3;
d7da2a10 5398 } else {
6c42444f 5399 env->npc = pc + 4;
d7da2a10 5400 }
d2856f1a
AJ
5401 } else {
5402 env->npc = npc;
5403 }
5404}