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