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