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