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