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