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