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