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