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