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