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