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