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