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