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