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