]> git.proxmox.com Git - mirror_qemu.git/blob - target/sparc/translate.c
hw/hyperv: Include missing headers
[mirror_qemu.git] / target / sparc / translate.c
1 /*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5 Copyright (C) 2003-2005 Fabrice Bellard
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "qemu/osdep.h"
22
23 #include "cpu.h"
24 #include "disas/disas.h"
25 #include "exec/helper-proto.h"
26 #include "exec/exec-all.h"
27 #include "tcg/tcg-op.h"
28 #include "tcg/tcg-op-gvec.h"
29 #include "exec/helper-gen.h"
30 #include "exec/translator.h"
31 #include "exec/log.h"
32 #include "asi.h"
33
34 #define HELPER_H "helper.h"
35 #include "exec/helper-info.c.inc"
36 #undef HELPER_H
37
38 #ifdef TARGET_SPARC64
39 # define gen_helper_rdpsr(D, E) qemu_build_not_reached()
40 # define gen_helper_rett(E) qemu_build_not_reached()
41 # define gen_helper_power_down(E) qemu_build_not_reached()
42 # define gen_helper_wrpsr(E, S) qemu_build_not_reached()
43 #else
44 # define gen_helper_clear_softint(E, S) qemu_build_not_reached()
45 # define gen_helper_done(E) qemu_build_not_reached()
46 # define gen_helper_fabsd(D, S) qemu_build_not_reached()
47 # define gen_helper_flushw(E) qemu_build_not_reached()
48 # define gen_helper_fnegd(D, S) qemu_build_not_reached()
49 # define gen_helper_rdccr(D, E) qemu_build_not_reached()
50 # define gen_helper_rdcwp(D, E) qemu_build_not_reached()
51 # define gen_helper_restored(E) qemu_build_not_reached()
52 # define gen_helper_retry(E) qemu_build_not_reached()
53 # define gen_helper_saved(E) qemu_build_not_reached()
54 # define gen_helper_set_softint(E, S) qemu_build_not_reached()
55 # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
56 # define gen_helper_tick_set_count(P, S) qemu_build_not_reached()
57 # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached()
58 # define gen_helper_wrccr(E, S) qemu_build_not_reached()
59 # define gen_helper_wrcwp(E, S) qemu_build_not_reached()
60 # define gen_helper_wrgl(E, S) qemu_build_not_reached()
61 # define gen_helper_write_softint(E, S) qemu_build_not_reached()
62 # define gen_helper_wrpil(E, S) qemu_build_not_reached()
63 # define gen_helper_wrpstate(E, S) qemu_build_not_reached()
64 # define gen_helper_fabsq ({ qemu_build_not_reached(); NULL; })
65 # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; })
66 # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; })
67 # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; })
68 # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; })
69 # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; })
70 # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; })
71 # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; })
72 # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; })
73 # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; })
74 # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; })
75 # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; })
76 # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; })
77 # define gen_helper_fmul8x16al ({ qemu_build_not_reached(); NULL; })
78 # define gen_helper_fmul8x16au ({ qemu_build_not_reached(); NULL; })
79 # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; })
80 # define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; })
81 # define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; })
82 # define gen_helper_fnegq ({ qemu_build_not_reached(); NULL; })
83 # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; })
84 # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; })
85 # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; })
86 # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; })
87 # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; })
88 # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; })
89 # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; })
90 # define FSR_LDXFSR_MASK 0
91 # define FSR_LDXFSR_OLDMASK 0
92 # define MAXTL_MASK 0
93 #endif
94
95 /* Dynamic PC, must exit to main loop. */
96 #define DYNAMIC_PC 1
97 /* Dynamic PC, one of two values according to jump_pc[T2]. */
98 #define JUMP_PC 2
99 /* Dynamic PC, may lookup next TB. */
100 #define DYNAMIC_PC_LOOKUP 3
101
102 #define DISAS_EXIT DISAS_TARGET_0
103
104 /* global register indexes */
105 static TCGv_ptr cpu_regwptr;
106 static TCGv cpu_fsr, cpu_pc, cpu_npc;
107 static TCGv cpu_regs[32];
108 static TCGv cpu_y;
109 static TCGv cpu_tbr;
110 static TCGv cpu_cond;
111 static TCGv cpu_cc_N;
112 static TCGv cpu_cc_V;
113 static TCGv cpu_icc_Z;
114 static TCGv cpu_icc_C;
115 #ifdef TARGET_SPARC64
116 static TCGv cpu_xcc_Z;
117 static TCGv cpu_xcc_C;
118 static TCGv_i32 cpu_fprs;
119 static TCGv cpu_gsr;
120 #else
121 # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; })
122 # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; })
123 #endif
124
125 #ifdef TARGET_SPARC64
126 #define cpu_cc_Z cpu_xcc_Z
127 #define cpu_cc_C cpu_xcc_C
128 #else
129 #define cpu_cc_Z cpu_icc_Z
130 #define cpu_cc_C cpu_icc_C
131 #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
132 #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
133 #endif
134
135 /* Floating point registers */
136 static TCGv_i64 cpu_fpr[TARGET_DPREGS];
137
138 #define env_field_offsetof(X) offsetof(CPUSPARCState, X)
139 #ifdef TARGET_SPARC64
140 # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
141 # define env64_field_offsetof(X) env_field_offsetof(X)
142 #else
143 # define env32_field_offsetof(X) env_field_offsetof(X)
144 # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
145 #endif
146
147 typedef struct DisasCompare {
148 TCGCond cond;
149 TCGv c1;
150 int c2;
151 } DisasCompare;
152
153 typedef struct DisasDelayException {
154 struct DisasDelayException *next;
155 TCGLabel *lab;
156 TCGv_i32 excp;
157 /* Saved state at parent insn. */
158 target_ulong pc;
159 target_ulong npc;
160 } DisasDelayException;
161
162 typedef struct DisasContext {
163 DisasContextBase base;
164 target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
165 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
166
167 /* Used when JUMP_PC value is used. */
168 DisasCompare jump;
169 target_ulong jump_pc[2];
170
171 int mem_idx;
172 bool cpu_cond_live;
173 bool fpu_enabled;
174 bool address_mask_32bit;
175 #ifndef CONFIG_USER_ONLY
176 bool supervisor;
177 #ifdef TARGET_SPARC64
178 bool hypervisor;
179 #endif
180 #endif
181
182 sparc_def_t *def;
183 #ifdef TARGET_SPARC64
184 int fprs_dirty;
185 int asi;
186 #endif
187 DisasDelayException *delay_excp_list;
188 } DisasContext;
189
190 // This function uses non-native bit order
191 #define GET_FIELD(X, FROM, TO) \
192 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
193
194 // This function uses the order in the manuals, i.e. bit 0 is 2^0
195 #define GET_FIELD_SP(X, FROM, TO) \
196 GET_FIELD(X, 31 - (TO), 31 - (FROM))
197
198 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
199 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
200
201 #ifdef TARGET_SPARC64
202 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
203 #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
204 #else
205 #define DFPREG(r) (r & 0x1e)
206 #define QFPREG(r) (r & 0x1c)
207 #endif
208
209 #define UA2005_HTRAP_MASK 0xff
210 #define V8_TRAP_MASK 0x7f
211
212 #define IS_IMM (insn & (1<<13))
213
214 static void gen_update_fprs_dirty(DisasContext *dc, int rd)
215 {
216 #if defined(TARGET_SPARC64)
217 int bit = (rd < 32) ? 1 : 2;
218 /* If we know we've already set this bit within the TB,
219 we can avoid setting it again. */
220 if (!(dc->fprs_dirty & bit)) {
221 dc->fprs_dirty |= bit;
222 tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
223 }
224 #endif
225 }
226
227 /* floating point registers moves */
228 static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
229 {
230 TCGv_i32 ret = tcg_temp_new_i32();
231 if (src & 1) {
232 tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]);
233 } else {
234 tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]);
235 }
236 return ret;
237 }
238
239 static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
240 {
241 TCGv_i64 t = tcg_temp_new_i64();
242
243 tcg_gen_extu_i32_i64(t, v);
244 tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
245 (dst & 1 ? 0 : 32), 32);
246 gen_update_fprs_dirty(dc, dst);
247 }
248
249 static TCGv_i32 gen_dest_fpr_F(DisasContext *dc)
250 {
251 return tcg_temp_new_i32();
252 }
253
254 static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
255 {
256 src = DFPREG(src);
257 return cpu_fpr[src / 2];
258 }
259
260 static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
261 {
262 dst = DFPREG(dst);
263 tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
264 gen_update_fprs_dirty(dc, dst);
265 }
266
267 static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
268 {
269 return cpu_fpr[DFPREG(dst) / 2];
270 }
271
272 static void gen_op_load_fpr_QT0(unsigned int src)
273 {
274 tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt0) +
275 offsetof(CPU_QuadU, ll.upper));
276 tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) +
277 offsetof(CPU_QuadU, ll.lower));
278 }
279
280 static void gen_op_load_fpr_QT1(unsigned int src)
281 {
282 tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt1) +
283 offsetof(CPU_QuadU, ll.upper));
284 tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt1) +
285 offsetof(CPU_QuadU, ll.lower));
286 }
287
288 static void gen_op_store_QT0_fpr(unsigned int dst)
289 {
290 tcg_gen_ld_i64(cpu_fpr[dst / 2], tcg_env, offsetof(CPUSPARCState, qt0) +
291 offsetof(CPU_QuadU, ll.upper));
292 tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) +
293 offsetof(CPU_QuadU, ll.lower));
294 }
295
296 /* moves */
297 #ifdef CONFIG_USER_ONLY
298 #define supervisor(dc) 0
299 #define hypervisor(dc) 0
300 #else
301 #ifdef TARGET_SPARC64
302 #define hypervisor(dc) (dc->hypervisor)
303 #define supervisor(dc) (dc->supervisor | dc->hypervisor)
304 #else
305 #define supervisor(dc) (dc->supervisor)
306 #define hypervisor(dc) 0
307 #endif
308 #endif
309
310 #if !defined(TARGET_SPARC64)
311 # define AM_CHECK(dc) false
312 #elif defined(TARGET_ABI32)
313 # define AM_CHECK(dc) true
314 #elif defined(CONFIG_USER_ONLY)
315 # define AM_CHECK(dc) false
316 #else
317 # define AM_CHECK(dc) ((dc)->address_mask_32bit)
318 #endif
319
320 static void gen_address_mask(DisasContext *dc, TCGv addr)
321 {
322 if (AM_CHECK(dc)) {
323 tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
324 }
325 }
326
327 static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
328 {
329 return AM_CHECK(dc) ? (uint32_t)addr : addr;
330 }
331
332 static TCGv gen_load_gpr(DisasContext *dc, int reg)
333 {
334 if (reg > 0) {
335 assert(reg < 32);
336 return cpu_regs[reg];
337 } else {
338 TCGv t = tcg_temp_new();
339 tcg_gen_movi_tl(t, 0);
340 return t;
341 }
342 }
343
344 static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
345 {
346 if (reg > 0) {
347 assert(reg < 32);
348 tcg_gen_mov_tl(cpu_regs[reg], v);
349 }
350 }
351
352 static TCGv gen_dest_gpr(DisasContext *dc, int reg)
353 {
354 if (reg > 0) {
355 assert(reg < 32);
356 return cpu_regs[reg];
357 } else {
358 return tcg_temp_new();
359 }
360 }
361
362 static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
363 {
364 return translator_use_goto_tb(&s->base, pc) &&
365 translator_use_goto_tb(&s->base, npc);
366 }
367
368 static void gen_goto_tb(DisasContext *s, int tb_num,
369 target_ulong pc, target_ulong npc)
370 {
371 if (use_goto_tb(s, pc, npc)) {
372 /* jump to same page: we can use a direct jump */
373 tcg_gen_goto_tb(tb_num);
374 tcg_gen_movi_tl(cpu_pc, pc);
375 tcg_gen_movi_tl(cpu_npc, npc);
376 tcg_gen_exit_tb(s->base.tb, tb_num);
377 } else {
378 /* jump to another page: we can use an indirect jump */
379 tcg_gen_movi_tl(cpu_pc, pc);
380 tcg_gen_movi_tl(cpu_npc, npc);
381 tcg_gen_lookup_and_goto_ptr();
382 }
383 }
384
385 static TCGv gen_carry32(void)
386 {
387 if (TARGET_LONG_BITS == 64) {
388 TCGv t = tcg_temp_new();
389 tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
390 return t;
391 }
392 return cpu_icc_C;
393 }
394
395 static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
396 {
397 TCGv z = tcg_constant_tl(0);
398
399 if (cin) {
400 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
401 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
402 } else {
403 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
404 }
405 tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
406 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
407 tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
408 if (TARGET_LONG_BITS == 64) {
409 /*
410 * Carry-in to bit 32 is result ^ src1 ^ src2.
411 * We already have the src xor term in Z, from computation of V.
412 */
413 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
414 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
415 }
416 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
417 tcg_gen_mov_tl(dst, cpu_cc_N);
418 }
419
420 static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
421 {
422 gen_op_addcc_int(dst, src1, src2, NULL);
423 }
424
425 static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
426 {
427 TCGv t = tcg_temp_new();
428
429 /* Save the tag bits around modification of dst. */
430 tcg_gen_or_tl(t, src1, src2);
431
432 gen_op_addcc(dst, src1, src2);
433
434 /* Incorprate tag bits into icc.V */
435 tcg_gen_andi_tl(t, t, 3);
436 tcg_gen_neg_tl(t, t);
437 tcg_gen_ext32u_tl(t, t);
438 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
439 }
440
441 static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
442 {
443 tcg_gen_add_tl(dst, src1, src2);
444 tcg_gen_add_tl(dst, dst, gen_carry32());
445 }
446
447 static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
448 {
449 gen_op_addcc_int(dst, src1, src2, gen_carry32());
450 }
451
452 static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
453 {
454 TCGv z = tcg_constant_tl(0);
455
456 if (cin) {
457 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
458 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
459 } else {
460 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
461 }
462 tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
463 tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
464 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
465 tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
466 #ifdef TARGET_SPARC64
467 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
468 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
469 #endif
470 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
471 tcg_gen_mov_tl(dst, cpu_cc_N);
472 }
473
474 static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
475 {
476 gen_op_subcc_int(dst, src1, src2, NULL);
477 }
478
479 static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
480 {
481 TCGv t = tcg_temp_new();
482
483 /* Save the tag bits around modification of dst. */
484 tcg_gen_or_tl(t, src1, src2);
485
486 gen_op_subcc(dst, src1, src2);
487
488 /* Incorprate tag bits into icc.V */
489 tcg_gen_andi_tl(t, t, 3);
490 tcg_gen_neg_tl(t, t);
491 tcg_gen_ext32u_tl(t, t);
492 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
493 }
494
495 static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
496 {
497 tcg_gen_sub_tl(dst, src1, src2);
498 tcg_gen_sub_tl(dst, dst, gen_carry32());
499 }
500
501 static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
502 {
503 gen_op_subcc_int(dst, src1, src2, gen_carry32());
504 }
505
506 static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
507 {
508 TCGv zero = tcg_constant_tl(0);
509 TCGv t_src1 = tcg_temp_new();
510 TCGv t_src2 = tcg_temp_new();
511 TCGv t0 = tcg_temp_new();
512
513 tcg_gen_ext32u_tl(t_src1, src1);
514 tcg_gen_ext32u_tl(t_src2, src2);
515
516 /*
517 * if (!(env->y & 1))
518 * src2 = 0;
519 */
520 tcg_gen_andi_tl(t0, cpu_y, 0x1);
521 tcg_gen_movcond_tl(TCG_COND_EQ, t_src2, t0, zero, zero, t_src2);
522
523 /*
524 * b2 = src1 & 1;
525 * y = (b2 << 31) | (y >> 1);
526 */
527 tcg_gen_extract_tl(t0, cpu_y, 1, 31);
528 tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
529
530 // b1 = N ^ V;
531 tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
532
533 /*
534 * src1 = (b1 << 31) | (src1 >> 1)
535 */
536 tcg_gen_andi_tl(t0, t0, 1u << 31);
537 tcg_gen_shri_tl(t_src1, t_src1, 1);
538 tcg_gen_or_tl(t_src1, t_src1, t0);
539
540 gen_op_addcc(dst, t_src1, t_src2);
541 }
542
543 static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
544 {
545 #if TARGET_LONG_BITS == 32
546 if (sign_ext) {
547 tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
548 } else {
549 tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
550 }
551 #else
552 TCGv t0 = tcg_temp_new_i64();
553 TCGv t1 = tcg_temp_new_i64();
554
555 if (sign_ext) {
556 tcg_gen_ext32s_i64(t0, src1);
557 tcg_gen_ext32s_i64(t1, src2);
558 } else {
559 tcg_gen_ext32u_i64(t0, src1);
560 tcg_gen_ext32u_i64(t1, src2);
561 }
562
563 tcg_gen_mul_i64(dst, t0, t1);
564 tcg_gen_shri_i64(cpu_y, dst, 32);
565 #endif
566 }
567
568 static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
569 {
570 /* zero-extend truncated operands before multiplication */
571 gen_op_multiply(dst, src1, src2, 0);
572 }
573
574 static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
575 {
576 /* sign-extend truncated operands before multiplication */
577 gen_op_multiply(dst, src1, src2, 1);
578 }
579
580 static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
581 {
582 #ifdef TARGET_SPARC64
583 gen_helper_sdiv(dst, tcg_env, src1, src2);
584 tcg_gen_ext32s_tl(dst, dst);
585 #else
586 TCGv_i64 t64 = tcg_temp_new_i64();
587 gen_helper_sdiv(t64, tcg_env, src1, src2);
588 tcg_gen_trunc_i64_tl(dst, t64);
589 #endif
590 }
591
592 static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
593 {
594 TCGv_i64 t64;
595
596 #ifdef TARGET_SPARC64
597 t64 = cpu_cc_V;
598 #else
599 t64 = tcg_temp_new_i64();
600 #endif
601
602 gen_helper_udiv(t64, tcg_env, src1, src2);
603
604 #ifdef TARGET_SPARC64
605 tcg_gen_ext32u_tl(cpu_cc_N, t64);
606 tcg_gen_shri_tl(cpu_cc_V, t64, 32);
607 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
608 tcg_gen_movi_tl(cpu_icc_C, 0);
609 #else
610 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
611 #endif
612 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
613 tcg_gen_movi_tl(cpu_cc_C, 0);
614 tcg_gen_mov_tl(dst, cpu_cc_N);
615 }
616
617 static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
618 {
619 TCGv_i64 t64;
620
621 #ifdef TARGET_SPARC64
622 t64 = cpu_cc_V;
623 #else
624 t64 = tcg_temp_new_i64();
625 #endif
626
627 gen_helper_sdiv(t64, tcg_env, src1, src2);
628
629 #ifdef TARGET_SPARC64
630 tcg_gen_ext32s_tl(cpu_cc_N, t64);
631 tcg_gen_shri_tl(cpu_cc_V, t64, 32);
632 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
633 tcg_gen_movi_tl(cpu_icc_C, 0);
634 #else
635 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
636 #endif
637 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
638 tcg_gen_movi_tl(cpu_cc_C, 0);
639 tcg_gen_mov_tl(dst, cpu_cc_N);
640 }
641
642 static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
643 {
644 gen_helper_taddcctv(dst, tcg_env, src1, src2);
645 }
646
647 static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
648 {
649 gen_helper_tsubcctv(dst, tcg_env, src1, src2);
650 }
651
652 static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
653 {
654 tcg_gen_ctpop_tl(dst, src2);
655 }
656
657 #ifndef TARGET_SPARC64
658 static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
659 {
660 g_assert_not_reached();
661 }
662 #endif
663
664 static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
665 {
666 gen_helper_array8(dst, src1, src2);
667 tcg_gen_shli_tl(dst, dst, 1);
668 }
669
670 static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
671 {
672 gen_helper_array8(dst, src1, src2);
673 tcg_gen_shli_tl(dst, dst, 2);
674 }
675
676 static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
677 {
678 #ifdef TARGET_SPARC64
679 gen_helper_fpack16(dst, cpu_gsr, src);
680 #else
681 g_assert_not_reached();
682 #endif
683 }
684
685 static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
686 {
687 #ifdef TARGET_SPARC64
688 gen_helper_fpackfix(dst, cpu_gsr, src);
689 #else
690 g_assert_not_reached();
691 #endif
692 }
693
694 static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
695 {
696 #ifdef TARGET_SPARC64
697 gen_helper_fpack32(dst, cpu_gsr, src1, src2);
698 #else
699 g_assert_not_reached();
700 #endif
701 }
702
703 static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
704 {
705 #ifdef TARGET_SPARC64
706 TCGv t1, t2, shift;
707
708 t1 = tcg_temp_new();
709 t2 = tcg_temp_new();
710 shift = tcg_temp_new();
711
712 tcg_gen_andi_tl(shift, cpu_gsr, 7);
713 tcg_gen_shli_tl(shift, shift, 3);
714 tcg_gen_shl_tl(t1, s1, shift);
715
716 /*
717 * A shift of 64 does not produce 0 in TCG. Divide this into a
718 * shift of (up to 63) followed by a constant shift of 1.
719 */
720 tcg_gen_xori_tl(shift, shift, 63);
721 tcg_gen_shr_tl(t2, s2, shift);
722 tcg_gen_shri_tl(t2, t2, 1);
723
724 tcg_gen_or_tl(dst, t1, t2);
725 #else
726 g_assert_not_reached();
727 #endif
728 }
729
730 static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
731 {
732 #ifdef TARGET_SPARC64
733 gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
734 #else
735 g_assert_not_reached();
736 #endif
737 }
738
739 // 1
740 static void gen_op_eval_ba(TCGv dst)
741 {
742 tcg_gen_movi_tl(dst, 1);
743 }
744
745 // 0
746 static void gen_op_eval_bn(TCGv dst)
747 {
748 tcg_gen_movi_tl(dst, 0);
749 }
750
751 /*
752 FPSR bit field FCC1 | FCC0:
753 0 =
754 1 <
755 2 >
756 3 unordered
757 */
758 static void gen_mov_reg_FCC0(TCGv reg, TCGv src,
759 unsigned int fcc_offset)
760 {
761 tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset);
762 tcg_gen_andi_tl(reg, reg, 0x1);
763 }
764
765 static void gen_mov_reg_FCC1(TCGv reg, TCGv src, unsigned int fcc_offset)
766 {
767 tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset);
768 tcg_gen_andi_tl(reg, reg, 0x1);
769 }
770
771 // !0: FCC0 | FCC1
772 static void gen_op_eval_fbne(TCGv dst, TCGv src, unsigned int fcc_offset)
773 {
774 TCGv t0 = tcg_temp_new();
775 gen_mov_reg_FCC0(dst, src, fcc_offset);
776 gen_mov_reg_FCC1(t0, src, fcc_offset);
777 tcg_gen_or_tl(dst, dst, t0);
778 }
779
780 // 1 or 2: FCC0 ^ FCC1
781 static void gen_op_eval_fblg(TCGv dst, TCGv src, unsigned int fcc_offset)
782 {
783 TCGv t0 = tcg_temp_new();
784 gen_mov_reg_FCC0(dst, src, fcc_offset);
785 gen_mov_reg_FCC1(t0, src, fcc_offset);
786 tcg_gen_xor_tl(dst, dst, t0);
787 }
788
789 // 1 or 3: FCC0
790 static void gen_op_eval_fbul(TCGv dst, TCGv src, unsigned int fcc_offset)
791 {
792 gen_mov_reg_FCC0(dst, src, fcc_offset);
793 }
794
795 // 1: FCC0 & !FCC1
796 static void gen_op_eval_fbl(TCGv dst, TCGv src, unsigned int fcc_offset)
797 {
798 TCGv t0 = tcg_temp_new();
799 gen_mov_reg_FCC0(dst, src, fcc_offset);
800 gen_mov_reg_FCC1(t0, src, fcc_offset);
801 tcg_gen_andc_tl(dst, dst, t0);
802 }
803
804 // 2 or 3: FCC1
805 static void gen_op_eval_fbug(TCGv dst, TCGv src, unsigned int fcc_offset)
806 {
807 gen_mov_reg_FCC1(dst, src, fcc_offset);
808 }
809
810 // 2: !FCC0 & FCC1
811 static void gen_op_eval_fbg(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_andc_tl(dst, t0, dst);
817 }
818
819 // 3: FCC0 & FCC1
820 static void gen_op_eval_fbu(TCGv dst, TCGv src, unsigned int fcc_offset)
821 {
822 TCGv t0 = tcg_temp_new();
823 gen_mov_reg_FCC0(dst, src, fcc_offset);
824 gen_mov_reg_FCC1(t0, src, fcc_offset);
825 tcg_gen_and_tl(dst, dst, t0);
826 }
827
828 // 0: !(FCC0 | FCC1)
829 static void gen_op_eval_fbe(TCGv dst, TCGv src, unsigned int fcc_offset)
830 {
831 TCGv t0 = tcg_temp_new();
832 gen_mov_reg_FCC0(dst, src, fcc_offset);
833 gen_mov_reg_FCC1(t0, src, fcc_offset);
834 tcg_gen_or_tl(dst, dst, t0);
835 tcg_gen_xori_tl(dst, dst, 0x1);
836 }
837
838 // 0 or 3: !(FCC0 ^ FCC1)
839 static void gen_op_eval_fbue(TCGv dst, TCGv src, unsigned int fcc_offset)
840 {
841 TCGv t0 = tcg_temp_new();
842 gen_mov_reg_FCC0(dst, src, fcc_offset);
843 gen_mov_reg_FCC1(t0, src, fcc_offset);
844 tcg_gen_xor_tl(dst, dst, t0);
845 tcg_gen_xori_tl(dst, dst, 0x1);
846 }
847
848 // 0 or 2: !FCC0
849 static void gen_op_eval_fbge(TCGv dst, TCGv src, unsigned int fcc_offset)
850 {
851 gen_mov_reg_FCC0(dst, src, fcc_offset);
852 tcg_gen_xori_tl(dst, dst, 0x1);
853 }
854
855 // !1: !(FCC0 & !FCC1)
856 static void gen_op_eval_fbuge(TCGv dst, TCGv src, unsigned int fcc_offset)
857 {
858 TCGv t0 = tcg_temp_new();
859 gen_mov_reg_FCC0(dst, src, fcc_offset);
860 gen_mov_reg_FCC1(t0, src, fcc_offset);
861 tcg_gen_andc_tl(dst, dst, t0);
862 tcg_gen_xori_tl(dst, dst, 0x1);
863 }
864
865 // 0 or 1: !FCC1
866 static void gen_op_eval_fble(TCGv dst, TCGv src, unsigned int fcc_offset)
867 {
868 gen_mov_reg_FCC1(dst, src, fcc_offset);
869 tcg_gen_xori_tl(dst, dst, 0x1);
870 }
871
872 // !2: !(!FCC0 & FCC1)
873 static void gen_op_eval_fbule(TCGv dst, TCGv src, unsigned int fcc_offset)
874 {
875 TCGv t0 = tcg_temp_new();
876 gen_mov_reg_FCC0(dst, src, fcc_offset);
877 gen_mov_reg_FCC1(t0, src, fcc_offset);
878 tcg_gen_andc_tl(dst, t0, dst);
879 tcg_gen_xori_tl(dst, dst, 0x1);
880 }
881
882 // !3: !(FCC0 & FCC1)
883 static void gen_op_eval_fbo(TCGv dst, TCGv src, unsigned int fcc_offset)
884 {
885 TCGv t0 = tcg_temp_new();
886 gen_mov_reg_FCC0(dst, src, fcc_offset);
887 gen_mov_reg_FCC1(t0, src, fcc_offset);
888 tcg_gen_and_tl(dst, dst, t0);
889 tcg_gen_xori_tl(dst, dst, 0x1);
890 }
891
892 static void finishing_insn(DisasContext *dc)
893 {
894 /*
895 * From here, there is no future path through an unwinding exception.
896 * If the current insn cannot raise an exception, the computation of
897 * cpu_cond may be able to be elided.
898 */
899 if (dc->cpu_cond_live) {
900 tcg_gen_discard_tl(cpu_cond);
901 dc->cpu_cond_live = false;
902 }
903 }
904
905 static void gen_generic_branch(DisasContext *dc)
906 {
907 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
908 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
909 TCGv c2 = tcg_constant_tl(dc->jump.c2);
910
911 tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
912 }
913
914 /* call this function before using the condition register as it may
915 have been set for a jump */
916 static void flush_cond(DisasContext *dc)
917 {
918 if (dc->npc == JUMP_PC) {
919 gen_generic_branch(dc);
920 dc->npc = DYNAMIC_PC_LOOKUP;
921 }
922 }
923
924 static void save_npc(DisasContext *dc)
925 {
926 if (dc->npc & 3) {
927 switch (dc->npc) {
928 case JUMP_PC:
929 gen_generic_branch(dc);
930 dc->npc = DYNAMIC_PC_LOOKUP;
931 break;
932 case DYNAMIC_PC:
933 case DYNAMIC_PC_LOOKUP:
934 break;
935 default:
936 g_assert_not_reached();
937 }
938 } else {
939 tcg_gen_movi_tl(cpu_npc, dc->npc);
940 }
941 }
942
943 static void save_state(DisasContext *dc)
944 {
945 tcg_gen_movi_tl(cpu_pc, dc->pc);
946 save_npc(dc);
947 }
948
949 static void gen_exception(DisasContext *dc, int which)
950 {
951 finishing_insn(dc);
952 save_state(dc);
953 gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
954 dc->base.is_jmp = DISAS_NORETURN;
955 }
956
957 static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
958 {
959 DisasDelayException *e = g_new0(DisasDelayException, 1);
960
961 e->next = dc->delay_excp_list;
962 dc->delay_excp_list = e;
963
964 e->lab = gen_new_label();
965 e->excp = excp;
966 e->pc = dc->pc;
967 /* Caller must have used flush_cond before branch. */
968 assert(e->npc != JUMP_PC);
969 e->npc = dc->npc;
970
971 return e->lab;
972 }
973
974 static TCGLabel *delay_exception(DisasContext *dc, int excp)
975 {
976 return delay_exceptionv(dc, tcg_constant_i32(excp));
977 }
978
979 static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
980 {
981 TCGv t = tcg_temp_new();
982 TCGLabel *lab;
983
984 tcg_gen_andi_tl(t, addr, mask);
985
986 flush_cond(dc);
987 lab = delay_exception(dc, TT_UNALIGNED);
988 tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
989 }
990
991 static void gen_mov_pc_npc(DisasContext *dc)
992 {
993 finishing_insn(dc);
994
995 if (dc->npc & 3) {
996 switch (dc->npc) {
997 case JUMP_PC:
998 gen_generic_branch(dc);
999 tcg_gen_mov_tl(cpu_pc, cpu_npc);
1000 dc->pc = DYNAMIC_PC_LOOKUP;
1001 break;
1002 case DYNAMIC_PC:
1003 case DYNAMIC_PC_LOOKUP:
1004 tcg_gen_mov_tl(cpu_pc, cpu_npc);
1005 dc->pc = dc->npc;
1006 break;
1007 default:
1008 g_assert_not_reached();
1009 }
1010 } else {
1011 dc->pc = dc->npc;
1012 }
1013 }
1014
1015 static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
1016 DisasContext *dc)
1017 {
1018 TCGv t1;
1019
1020 cmp->c1 = t1 = tcg_temp_new();
1021 cmp->c2 = 0;
1022
1023 switch (cond & 7) {
1024 case 0x0: /* never */
1025 cmp->cond = TCG_COND_NEVER;
1026 cmp->c1 = tcg_constant_tl(0);
1027 break;
1028
1029 case 0x1: /* eq: Z */
1030 cmp->cond = TCG_COND_EQ;
1031 if (TARGET_LONG_BITS == 32 || xcc) {
1032 tcg_gen_mov_tl(t1, cpu_cc_Z);
1033 } else {
1034 tcg_gen_ext32u_tl(t1, cpu_icc_Z);
1035 }
1036 break;
1037
1038 case 0x2: /* le: Z | (N ^ V) */
1039 /*
1040 * Simplify:
1041 * cc_Z || (N ^ V) < 0 NE
1042 * cc_Z && !((N ^ V) < 0) EQ
1043 * cc_Z & ~((N ^ V) >> TLB) EQ
1044 */
1045 cmp->cond = TCG_COND_EQ;
1046 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
1047 tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
1048 tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
1049 if (TARGET_LONG_BITS == 64 && !xcc) {
1050 tcg_gen_ext32u_tl(t1, t1);
1051 }
1052 break;
1053
1054 case 0x3: /* lt: N ^ V */
1055 cmp->cond = TCG_COND_LT;
1056 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
1057 if (TARGET_LONG_BITS == 64 && !xcc) {
1058 tcg_gen_ext32s_tl(t1, t1);
1059 }
1060 break;
1061
1062 case 0x4: /* leu: Z | C */
1063 /*
1064 * Simplify:
1065 * cc_Z == 0 || cc_C != 0 NE
1066 * cc_Z != 0 && cc_C == 0 EQ
1067 * cc_Z & (cc_C ? 0 : -1) EQ
1068 * cc_Z & (cc_C - 1) EQ
1069 */
1070 cmp->cond = TCG_COND_EQ;
1071 if (TARGET_LONG_BITS == 32 || xcc) {
1072 tcg_gen_subi_tl(t1, cpu_cc_C, 1);
1073 tcg_gen_and_tl(t1, t1, cpu_cc_Z);
1074 } else {
1075 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
1076 tcg_gen_subi_tl(t1, t1, 1);
1077 tcg_gen_and_tl(t1, t1, cpu_icc_Z);
1078 tcg_gen_ext32u_tl(t1, t1);
1079 }
1080 break;
1081
1082 case 0x5: /* ltu: C */
1083 cmp->cond = TCG_COND_NE;
1084 if (TARGET_LONG_BITS == 32 || xcc) {
1085 tcg_gen_mov_tl(t1, cpu_cc_C);
1086 } else {
1087 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
1088 }
1089 break;
1090
1091 case 0x6: /* neg: N */
1092 cmp->cond = TCG_COND_LT;
1093 if (TARGET_LONG_BITS == 32 || xcc) {
1094 tcg_gen_mov_tl(t1, cpu_cc_N);
1095 } else {
1096 tcg_gen_ext32s_tl(t1, cpu_cc_N);
1097 }
1098 break;
1099
1100 case 0x7: /* vs: V */
1101 cmp->cond = TCG_COND_LT;
1102 if (TARGET_LONG_BITS == 32 || xcc) {
1103 tcg_gen_mov_tl(t1, cpu_cc_V);
1104 } else {
1105 tcg_gen_ext32s_tl(t1, cpu_cc_V);
1106 }
1107 break;
1108 }
1109 if (cond & 8) {
1110 cmp->cond = tcg_invert_cond(cmp->cond);
1111 }
1112 }
1113
1114 static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
1115 {
1116 unsigned int offset;
1117 TCGv r_dst;
1118
1119 /* For now we still generate a straight boolean result. */
1120 cmp->cond = TCG_COND_NE;
1121 cmp->c1 = r_dst = tcg_temp_new();
1122 cmp->c2 = 0;
1123
1124 switch (cc) {
1125 default:
1126 case 0x0:
1127 offset = 0;
1128 break;
1129 case 0x1:
1130 offset = 32 - 10;
1131 break;
1132 case 0x2:
1133 offset = 34 - 10;
1134 break;
1135 case 0x3:
1136 offset = 36 - 10;
1137 break;
1138 }
1139
1140 switch (cond) {
1141 case 0x0:
1142 gen_op_eval_bn(r_dst);
1143 break;
1144 case 0x1:
1145 gen_op_eval_fbne(r_dst, cpu_fsr, offset);
1146 break;
1147 case 0x2:
1148 gen_op_eval_fblg(r_dst, cpu_fsr, offset);
1149 break;
1150 case 0x3:
1151 gen_op_eval_fbul(r_dst, cpu_fsr, offset);
1152 break;
1153 case 0x4:
1154 gen_op_eval_fbl(r_dst, cpu_fsr, offset);
1155 break;
1156 case 0x5:
1157 gen_op_eval_fbug(r_dst, cpu_fsr, offset);
1158 break;
1159 case 0x6:
1160 gen_op_eval_fbg(r_dst, cpu_fsr, offset);
1161 break;
1162 case 0x7:
1163 gen_op_eval_fbu(r_dst, cpu_fsr, offset);
1164 break;
1165 case 0x8:
1166 gen_op_eval_ba(r_dst);
1167 break;
1168 case 0x9:
1169 gen_op_eval_fbe(r_dst, cpu_fsr, offset);
1170 break;
1171 case 0xa:
1172 gen_op_eval_fbue(r_dst, cpu_fsr, offset);
1173 break;
1174 case 0xb:
1175 gen_op_eval_fbge(r_dst, cpu_fsr, offset);
1176 break;
1177 case 0xc:
1178 gen_op_eval_fbuge(r_dst, cpu_fsr, offset);
1179 break;
1180 case 0xd:
1181 gen_op_eval_fble(r_dst, cpu_fsr, offset);
1182 break;
1183 case 0xe:
1184 gen_op_eval_fbule(r_dst, cpu_fsr, offset);
1185 break;
1186 case 0xf:
1187 gen_op_eval_fbo(r_dst, cpu_fsr, offset);
1188 break;
1189 }
1190 }
1191
1192 static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
1193 {
1194 static const TCGCond cond_reg[4] = {
1195 TCG_COND_NEVER, /* reserved */
1196 TCG_COND_EQ,
1197 TCG_COND_LE,
1198 TCG_COND_LT,
1199 };
1200 TCGCond tcond;
1201
1202 if ((cond & 3) == 0) {
1203 return false;
1204 }
1205 tcond = cond_reg[cond & 3];
1206 if (cond & 4) {
1207 tcond = tcg_invert_cond(tcond);
1208 }
1209
1210 cmp->cond = tcond;
1211 cmp->c1 = tcg_temp_new();
1212 cmp->c2 = 0;
1213 tcg_gen_mov_tl(cmp->c1, r_src);
1214 return true;
1215 }
1216
1217 static void gen_op_clear_ieee_excp_and_FTT(void)
1218 {
1219 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
1220 }
1221
1222 static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1223 {
1224 gen_op_clear_ieee_excp_and_FTT();
1225 tcg_gen_mov_i32(dst, src);
1226 }
1227
1228 static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1229 {
1230 gen_op_clear_ieee_excp_and_FTT();
1231 gen_helper_fnegs(dst, src);
1232 }
1233
1234 static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1235 {
1236 gen_op_clear_ieee_excp_and_FTT();
1237 gen_helper_fabss(dst, src);
1238 }
1239
1240 static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1241 {
1242 gen_op_clear_ieee_excp_and_FTT();
1243 tcg_gen_mov_i64(dst, src);
1244 }
1245
1246 static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1247 {
1248 gen_op_clear_ieee_excp_and_FTT();
1249 gen_helper_fnegd(dst, src);
1250 }
1251
1252 static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1253 {
1254 gen_op_clear_ieee_excp_and_FTT();
1255 gen_helper_fabsd(dst, src);
1256 }
1257
1258 #ifdef TARGET_SPARC64
1259 static void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1260 {
1261 switch (fccno) {
1262 case 0:
1263 gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2);
1264 break;
1265 case 1:
1266 gen_helper_fcmps_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
1267 break;
1268 case 2:
1269 gen_helper_fcmps_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
1270 break;
1271 case 3:
1272 gen_helper_fcmps_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
1273 break;
1274 }
1275 }
1276
1277 static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1278 {
1279 switch (fccno) {
1280 case 0:
1281 gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2);
1282 break;
1283 case 1:
1284 gen_helper_fcmpd_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
1285 break;
1286 case 2:
1287 gen_helper_fcmpd_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
1288 break;
1289 case 3:
1290 gen_helper_fcmpd_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
1291 break;
1292 }
1293 }
1294
1295 static void gen_op_fcmpq(int fccno)
1296 {
1297 switch (fccno) {
1298 case 0:
1299 gen_helper_fcmpq(cpu_fsr, tcg_env);
1300 break;
1301 case 1:
1302 gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env);
1303 break;
1304 case 2:
1305 gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env);
1306 break;
1307 case 3:
1308 gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env);
1309 break;
1310 }
1311 }
1312
1313 static void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1314 {
1315 switch (fccno) {
1316 case 0:
1317 gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2);
1318 break;
1319 case 1:
1320 gen_helper_fcmpes_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
1321 break;
1322 case 2:
1323 gen_helper_fcmpes_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
1324 break;
1325 case 3:
1326 gen_helper_fcmpes_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
1327 break;
1328 }
1329 }
1330
1331 static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1332 {
1333 switch (fccno) {
1334 case 0:
1335 gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2);
1336 break;
1337 case 1:
1338 gen_helper_fcmped_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
1339 break;
1340 case 2:
1341 gen_helper_fcmped_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
1342 break;
1343 case 3:
1344 gen_helper_fcmped_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
1345 break;
1346 }
1347 }
1348
1349 static void gen_op_fcmpeq(int fccno)
1350 {
1351 switch (fccno) {
1352 case 0:
1353 gen_helper_fcmpeq(cpu_fsr, tcg_env);
1354 break;
1355 case 1:
1356 gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env);
1357 break;
1358 case 2:
1359 gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env);
1360 break;
1361 case 3:
1362 gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env);
1363 break;
1364 }
1365 }
1366
1367 #else
1368
1369 static void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
1370 {
1371 gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2);
1372 }
1373
1374 static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1375 {
1376 gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2);
1377 }
1378
1379 static void gen_op_fcmpq(int fccno)
1380 {
1381 gen_helper_fcmpq(cpu_fsr, tcg_env);
1382 }
1383
1384 static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
1385 {
1386 gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2);
1387 }
1388
1389 static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1390 {
1391 gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2);
1392 }
1393
1394 static void gen_op_fcmpeq(int fccno)
1395 {
1396 gen_helper_fcmpeq(cpu_fsr, tcg_env);
1397 }
1398 #endif
1399
1400 static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags)
1401 {
1402 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
1403 tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
1404 gen_exception(dc, TT_FP_EXCP);
1405 }
1406
1407 static int gen_trap_ifnofpu(DisasContext *dc)
1408 {
1409 #if !defined(CONFIG_USER_ONLY)
1410 if (!dc->fpu_enabled) {
1411 gen_exception(dc, TT_NFPU_INSN);
1412 return 1;
1413 }
1414 #endif
1415 return 0;
1416 }
1417
1418 /* asi moves */
1419 typedef enum {
1420 GET_ASI_HELPER,
1421 GET_ASI_EXCP,
1422 GET_ASI_DIRECT,
1423 GET_ASI_DTWINX,
1424 GET_ASI_BLOCK,
1425 GET_ASI_SHORT,
1426 GET_ASI_BCOPY,
1427 GET_ASI_BFILL,
1428 } ASIType;
1429
1430 typedef struct {
1431 ASIType type;
1432 int asi;
1433 int mem_idx;
1434 MemOp memop;
1435 } DisasASI;
1436
1437 /*
1438 * Build DisasASI.
1439 * For asi == -1, treat as non-asi.
1440 * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1441 */
1442 static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
1443 {
1444 ASIType type = GET_ASI_HELPER;
1445 int mem_idx = dc->mem_idx;
1446
1447 if (asi == -1) {
1448 /* Artificial "non-asi" case. */
1449 type = GET_ASI_DIRECT;
1450 goto done;
1451 }
1452
1453 #ifndef TARGET_SPARC64
1454 /* Before v9, all asis are immediate and privileged. */
1455 if (asi < 0) {
1456 gen_exception(dc, TT_ILL_INSN);
1457 type = GET_ASI_EXCP;
1458 } else if (supervisor(dc)
1459 /* Note that LEON accepts ASI_USERDATA in user mode, for
1460 use with CASA. Also note that previous versions of
1461 QEMU allowed (and old versions of gcc emitted) ASI_P
1462 for LEON, which is incorrect. */
1463 || (asi == ASI_USERDATA
1464 && (dc->def->features & CPU_FEATURE_CASA))) {
1465 switch (asi) {
1466 case ASI_USERDATA: /* User data access */
1467 mem_idx = MMU_USER_IDX;
1468 type = GET_ASI_DIRECT;
1469 break;
1470 case ASI_KERNELDATA: /* Supervisor data access */
1471 mem_idx = MMU_KERNEL_IDX;
1472 type = GET_ASI_DIRECT;
1473 break;
1474 case ASI_M_BYPASS: /* MMU passthrough */
1475 case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1476 mem_idx = MMU_PHYS_IDX;
1477 type = GET_ASI_DIRECT;
1478 break;
1479 case ASI_M_BCOPY: /* Block copy, sta access */
1480 mem_idx = MMU_KERNEL_IDX;
1481 type = GET_ASI_BCOPY;
1482 break;
1483 case ASI_M_BFILL: /* Block fill, stda access */
1484 mem_idx = MMU_KERNEL_IDX;
1485 type = GET_ASI_BFILL;
1486 break;
1487 }
1488
1489 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
1490 * permissions check in get_physical_address(..).
1491 */
1492 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1493 } else {
1494 gen_exception(dc, TT_PRIV_INSN);
1495 type = GET_ASI_EXCP;
1496 }
1497 #else
1498 if (asi < 0) {
1499 asi = dc->asi;
1500 }
1501 /* With v9, all asis below 0x80 are privileged. */
1502 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1503 down that bit into DisasContext. For the moment that's ok,
1504 since the direct implementations below doesn't have any ASIs
1505 in the restricted [0x30, 0x7f] range, and the check will be
1506 done properly in the helper. */
1507 if (!supervisor(dc) && asi < 0x80) {
1508 gen_exception(dc, TT_PRIV_ACT);
1509 type = GET_ASI_EXCP;
1510 } else {
1511 switch (asi) {
1512 case ASI_REAL: /* Bypass */
1513 case ASI_REAL_IO: /* Bypass, non-cacheable */
1514 case ASI_REAL_L: /* Bypass LE */
1515 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
1516 case ASI_TWINX_REAL: /* Real address, twinx */
1517 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
1518 case ASI_QUAD_LDD_PHYS:
1519 case ASI_QUAD_LDD_PHYS_L:
1520 mem_idx = MMU_PHYS_IDX;
1521 break;
1522 case ASI_N: /* Nucleus */
1523 case ASI_NL: /* Nucleus LE */
1524 case ASI_TWINX_N:
1525 case ASI_TWINX_NL:
1526 case ASI_NUCLEUS_QUAD_LDD:
1527 case ASI_NUCLEUS_QUAD_LDD_L:
1528 if (hypervisor(dc)) {
1529 mem_idx = MMU_PHYS_IDX;
1530 } else {
1531 mem_idx = MMU_NUCLEUS_IDX;
1532 }
1533 break;
1534 case ASI_AIUP: /* As if user primary */
1535 case ASI_AIUPL: /* As if user primary LE */
1536 case ASI_TWINX_AIUP:
1537 case ASI_TWINX_AIUP_L:
1538 case ASI_BLK_AIUP_4V:
1539 case ASI_BLK_AIUP_L_4V:
1540 case ASI_BLK_AIUP:
1541 case ASI_BLK_AIUPL:
1542 mem_idx = MMU_USER_IDX;
1543 break;
1544 case ASI_AIUS: /* As if user secondary */
1545 case ASI_AIUSL: /* As if user secondary LE */
1546 case ASI_TWINX_AIUS:
1547 case ASI_TWINX_AIUS_L:
1548 case ASI_BLK_AIUS_4V:
1549 case ASI_BLK_AIUS_L_4V:
1550 case ASI_BLK_AIUS:
1551 case ASI_BLK_AIUSL:
1552 mem_idx = MMU_USER_SECONDARY_IDX;
1553 break;
1554 case ASI_S: /* Secondary */
1555 case ASI_SL: /* Secondary LE */
1556 case ASI_TWINX_S:
1557 case ASI_TWINX_SL:
1558 case ASI_BLK_COMMIT_S:
1559 case ASI_BLK_S:
1560 case ASI_BLK_SL:
1561 case ASI_FL8_S:
1562 case ASI_FL8_SL:
1563 case ASI_FL16_S:
1564 case ASI_FL16_SL:
1565 if (mem_idx == MMU_USER_IDX) {
1566 mem_idx = MMU_USER_SECONDARY_IDX;
1567 } else if (mem_idx == MMU_KERNEL_IDX) {
1568 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1569 }
1570 break;
1571 case ASI_P: /* Primary */
1572 case ASI_PL: /* Primary LE */
1573 case ASI_TWINX_P:
1574 case ASI_TWINX_PL:
1575 case ASI_BLK_COMMIT_P:
1576 case ASI_BLK_P:
1577 case ASI_BLK_PL:
1578 case ASI_FL8_P:
1579 case ASI_FL8_PL:
1580 case ASI_FL16_P:
1581 case ASI_FL16_PL:
1582 break;
1583 }
1584 switch (asi) {
1585 case ASI_REAL:
1586 case ASI_REAL_IO:
1587 case ASI_REAL_L:
1588 case ASI_REAL_IO_L:
1589 case ASI_N:
1590 case ASI_NL:
1591 case ASI_AIUP:
1592 case ASI_AIUPL:
1593 case ASI_AIUS:
1594 case ASI_AIUSL:
1595 case ASI_S:
1596 case ASI_SL:
1597 case ASI_P:
1598 case ASI_PL:
1599 type = GET_ASI_DIRECT;
1600 break;
1601 case ASI_TWINX_REAL:
1602 case ASI_TWINX_REAL_L:
1603 case ASI_TWINX_N:
1604 case ASI_TWINX_NL:
1605 case ASI_TWINX_AIUP:
1606 case ASI_TWINX_AIUP_L:
1607 case ASI_TWINX_AIUS:
1608 case ASI_TWINX_AIUS_L:
1609 case ASI_TWINX_P:
1610 case ASI_TWINX_PL:
1611 case ASI_TWINX_S:
1612 case ASI_TWINX_SL:
1613 case ASI_QUAD_LDD_PHYS:
1614 case ASI_QUAD_LDD_PHYS_L:
1615 case ASI_NUCLEUS_QUAD_LDD:
1616 case ASI_NUCLEUS_QUAD_LDD_L:
1617 type = GET_ASI_DTWINX;
1618 break;
1619 case ASI_BLK_COMMIT_P:
1620 case ASI_BLK_COMMIT_S:
1621 case ASI_BLK_AIUP_4V:
1622 case ASI_BLK_AIUP_L_4V:
1623 case ASI_BLK_AIUP:
1624 case ASI_BLK_AIUPL:
1625 case ASI_BLK_AIUS_4V:
1626 case ASI_BLK_AIUS_L_4V:
1627 case ASI_BLK_AIUS:
1628 case ASI_BLK_AIUSL:
1629 case ASI_BLK_S:
1630 case ASI_BLK_SL:
1631 case ASI_BLK_P:
1632 case ASI_BLK_PL:
1633 type = GET_ASI_BLOCK;
1634 break;
1635 case ASI_FL8_S:
1636 case ASI_FL8_SL:
1637 case ASI_FL8_P:
1638 case ASI_FL8_PL:
1639 memop = MO_UB;
1640 type = GET_ASI_SHORT;
1641 break;
1642 case ASI_FL16_S:
1643 case ASI_FL16_SL:
1644 case ASI_FL16_P:
1645 case ASI_FL16_PL:
1646 memop = MO_TEUW;
1647 type = GET_ASI_SHORT;
1648 break;
1649 }
1650 /* The little-endian asis all have bit 3 set. */
1651 if (asi & 8) {
1652 memop ^= MO_BSWAP;
1653 }
1654 }
1655 #endif
1656
1657 done:
1658 return (DisasASI){ type, asi, mem_idx, memop };
1659 }
1660
1661 #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1662 static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1663 TCGv_i32 asi, TCGv_i32 mop)
1664 {
1665 g_assert_not_reached();
1666 }
1667
1668 static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1669 TCGv_i32 asi, TCGv_i32 mop)
1670 {
1671 g_assert_not_reached();
1672 }
1673 #endif
1674
1675 static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1676 {
1677 switch (da->type) {
1678 case GET_ASI_EXCP:
1679 break;
1680 case GET_ASI_DTWINX: /* Reserved for ldda. */
1681 gen_exception(dc, TT_ILL_INSN);
1682 break;
1683 case GET_ASI_DIRECT:
1684 tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
1685 break;
1686 default:
1687 {
1688 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1689 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1690
1691 save_state(dc);
1692 #ifdef TARGET_SPARC64
1693 gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
1694 #else
1695 {
1696 TCGv_i64 t64 = tcg_temp_new_i64();
1697 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1698 tcg_gen_trunc_i64_tl(dst, t64);
1699 }
1700 #endif
1701 }
1702 break;
1703 }
1704 }
1705
1706 static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
1707 {
1708 switch (da->type) {
1709 case GET_ASI_EXCP:
1710 break;
1711
1712 case GET_ASI_DTWINX: /* Reserved for stda. */
1713 if (TARGET_LONG_BITS == 32) {
1714 gen_exception(dc, TT_ILL_INSN);
1715 break;
1716 } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
1717 /* Pre OpenSPARC CPUs don't have these */
1718 gen_exception(dc, TT_ILL_INSN);
1719 break;
1720 }
1721 /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
1722 /* fall through */
1723
1724 case GET_ASI_DIRECT:
1725 tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
1726 break;
1727
1728 case GET_ASI_BCOPY:
1729 assert(TARGET_LONG_BITS == 32);
1730 /* Copy 32 bytes from the address in SRC to ADDR. */
1731 /* ??? The original qemu code suggests 4-byte alignment, dropping
1732 the low bits, but the only place I can see this used is in the
1733 Linux kernel with 32 byte alignment, which would make more sense
1734 as a cacheline-style operation. */
1735 {
1736 TCGv saddr = tcg_temp_new();
1737 TCGv daddr = tcg_temp_new();
1738 TCGv four = tcg_constant_tl(4);
1739 TCGv_i32 tmp = tcg_temp_new_i32();
1740 int i;
1741
1742 tcg_gen_andi_tl(saddr, src, -4);
1743 tcg_gen_andi_tl(daddr, addr, -4);
1744 for (i = 0; i < 32; i += 4) {
1745 /* Since the loads and stores are paired, allow the
1746 copy to happen in the host endianness. */
1747 tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL);
1748 tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL);
1749 tcg_gen_add_tl(saddr, saddr, four);
1750 tcg_gen_add_tl(daddr, daddr, four);
1751 }
1752 }
1753 break;
1754
1755 default:
1756 {
1757 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1758 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1759
1760 save_state(dc);
1761 #ifdef TARGET_SPARC64
1762 gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
1763 #else
1764 {
1765 TCGv_i64 t64 = tcg_temp_new_i64();
1766 tcg_gen_extu_tl_i64(t64, src);
1767 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1768 }
1769 #endif
1770
1771 /* A write to a TLB register may alter page maps. End the TB. */
1772 dc->npc = DYNAMIC_PC;
1773 }
1774 break;
1775 }
1776 }
1777
1778 static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1779 TCGv dst, TCGv src, TCGv addr)
1780 {
1781 switch (da->type) {
1782 case GET_ASI_EXCP:
1783 break;
1784 case GET_ASI_DIRECT:
1785 tcg_gen_atomic_xchg_tl(dst, addr, src,
1786 da->mem_idx, da->memop | MO_ALIGN);
1787 break;
1788 default:
1789 /* ??? Should be DAE_invalid_asi. */
1790 gen_exception(dc, TT_DATA_ACCESS);
1791 break;
1792 }
1793 }
1794
1795 static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1796 TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
1797 {
1798 switch (da->type) {
1799 case GET_ASI_EXCP:
1800 return;
1801 case GET_ASI_DIRECT:
1802 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1803 da->mem_idx, da->memop | MO_ALIGN);
1804 break;
1805 default:
1806 /* ??? Should be DAE_invalid_asi. */
1807 gen_exception(dc, TT_DATA_ACCESS);
1808 break;
1809 }
1810 }
1811
1812 static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1813 {
1814 switch (da->type) {
1815 case GET_ASI_EXCP:
1816 break;
1817 case GET_ASI_DIRECT:
1818 tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1819 da->mem_idx, MO_UB);
1820 break;
1821 default:
1822 /* ??? In theory, this should be raise DAE_invalid_asi.
1823 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
1824 if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
1825 gen_helper_exit_atomic(tcg_env);
1826 } else {
1827 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1828 TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
1829 TCGv_i64 s64, t64;
1830
1831 save_state(dc);
1832 t64 = tcg_temp_new_i64();
1833 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1834
1835 s64 = tcg_constant_i64(0xff);
1836 gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
1837
1838 tcg_gen_trunc_i64_tl(dst, t64);
1839
1840 /* End the TB. */
1841 dc->npc = DYNAMIC_PC;
1842 }
1843 break;
1844 }
1845 }
1846
1847 static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
1848 TCGv addr, int rd)
1849 {
1850 MemOp memop = da->memop;
1851 MemOp size = memop & MO_SIZE;
1852 TCGv_i32 d32;
1853 TCGv_i64 d64;
1854 TCGv addr_tmp;
1855
1856 /* TODO: Use 128-bit load/store below. */
1857 if (size == MO_128) {
1858 memop = (memop & ~MO_SIZE) | MO_64;
1859 }
1860
1861 switch (da->type) {
1862 case GET_ASI_EXCP:
1863 break;
1864
1865 case GET_ASI_DIRECT:
1866 memop |= MO_ALIGN_4;
1867 switch (size) {
1868 case MO_32:
1869 d32 = gen_dest_fpr_F(dc);
1870 tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
1871 gen_store_fpr_F(dc, rd, d32);
1872 break;
1873
1874 case MO_64:
1875 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop);
1876 break;
1877
1878 case MO_128:
1879 d64 = tcg_temp_new_i64();
1880 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
1881 addr_tmp = tcg_temp_new();
1882 tcg_gen_addi_tl(addr_tmp, addr, 8);
1883 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
1884 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
1885 break;
1886 default:
1887 g_assert_not_reached();
1888 }
1889 break;
1890
1891 case GET_ASI_BLOCK:
1892 /* Valid for lddfa on aligned registers only. */
1893 if (orig_size == MO_64 && (rd & 7) == 0) {
1894 /* The first operation checks required alignment. */
1895 addr_tmp = tcg_temp_new();
1896 for (int i = 0; ; ++i) {
1897 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
1898 memop | (i == 0 ? MO_ALIGN_64 : 0));
1899 if (i == 7) {
1900 break;
1901 }
1902 tcg_gen_addi_tl(addr_tmp, addr, 8);
1903 addr = addr_tmp;
1904 }
1905 } else {
1906 gen_exception(dc, TT_ILL_INSN);
1907 }
1908 break;
1909
1910 case GET_ASI_SHORT:
1911 /* Valid for lddfa only. */
1912 if (orig_size == MO_64) {
1913 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
1914 memop | MO_ALIGN);
1915 } else {
1916 gen_exception(dc, TT_ILL_INSN);
1917 }
1918 break;
1919
1920 default:
1921 {
1922 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1923 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
1924
1925 save_state(dc);
1926 /* According to the table in the UA2011 manual, the only
1927 other asis that are valid for ldfa/lddfa/ldqfa are
1928 the NO_FAULT asis. We still need a helper for these,
1929 but we can just use the integer asi helper for them. */
1930 switch (size) {
1931 case MO_32:
1932 d64 = tcg_temp_new_i64();
1933 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1934 d32 = gen_dest_fpr_F(dc);
1935 tcg_gen_extrl_i64_i32(d32, d64);
1936 gen_store_fpr_F(dc, rd, d32);
1937 break;
1938 case MO_64:
1939 gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr,
1940 r_asi, r_mop);
1941 break;
1942 case MO_128:
1943 d64 = tcg_temp_new_i64();
1944 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1945 addr_tmp = tcg_temp_new();
1946 tcg_gen_addi_tl(addr_tmp, addr, 8);
1947 gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp,
1948 r_asi, r_mop);
1949 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
1950 break;
1951 default:
1952 g_assert_not_reached();
1953 }
1954 }
1955 break;
1956 }
1957 }
1958
1959 static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
1960 TCGv addr, int rd)
1961 {
1962 MemOp memop = da->memop;
1963 MemOp size = memop & MO_SIZE;
1964 TCGv_i32 d32;
1965 TCGv addr_tmp;
1966
1967 /* TODO: Use 128-bit load/store below. */
1968 if (size == MO_128) {
1969 memop = (memop & ~MO_SIZE) | MO_64;
1970 }
1971
1972 switch (da->type) {
1973 case GET_ASI_EXCP:
1974 break;
1975
1976 case GET_ASI_DIRECT:
1977 memop |= MO_ALIGN_4;
1978 switch (size) {
1979 case MO_32:
1980 d32 = gen_load_fpr_F(dc, rd);
1981 tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
1982 break;
1983 case MO_64:
1984 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
1985 memop | MO_ALIGN_4);
1986 break;
1987 case MO_128:
1988 /* Only 4-byte alignment required. However, it is legal for the
1989 cpu to signal the alignment fault, and the OS trap handler is
1990 required to fix it up. Requiring 16-byte alignment here avoids
1991 having to probe the second page before performing the first
1992 write. */
1993 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
1994 memop | MO_ALIGN_16);
1995 addr_tmp = tcg_temp_new();
1996 tcg_gen_addi_tl(addr_tmp, addr, 8);
1997 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
1998 break;
1999 default:
2000 g_assert_not_reached();
2001 }
2002 break;
2003
2004 case GET_ASI_BLOCK:
2005 /* Valid for stdfa on aligned registers only. */
2006 if (orig_size == MO_64 && (rd & 7) == 0) {
2007 /* The first operation checks required alignment. */
2008 addr_tmp = tcg_temp_new();
2009 for (int i = 0; ; ++i) {
2010 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
2011 memop | (i == 0 ? MO_ALIGN_64 : 0));
2012 if (i == 7) {
2013 break;
2014 }
2015 tcg_gen_addi_tl(addr_tmp, addr, 8);
2016 addr = addr_tmp;
2017 }
2018 } else {
2019 gen_exception(dc, TT_ILL_INSN);
2020 }
2021 break;
2022
2023 case GET_ASI_SHORT:
2024 /* Valid for stdfa only. */
2025 if (orig_size == MO_64) {
2026 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
2027 memop | MO_ALIGN);
2028 } else {
2029 gen_exception(dc, TT_ILL_INSN);
2030 }
2031 break;
2032
2033 default:
2034 /* According to the table in the UA2011 manual, the only
2035 other asis that are valid for ldfa/lddfa/ldqfa are
2036 the PST* asis, which aren't currently handled. */
2037 gen_exception(dc, TT_ILL_INSN);
2038 break;
2039 }
2040 }
2041
2042 static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2043 {
2044 TCGv hi = gen_dest_gpr(dc, rd);
2045 TCGv lo = gen_dest_gpr(dc, rd + 1);
2046
2047 switch (da->type) {
2048 case GET_ASI_EXCP:
2049 return;
2050
2051 case GET_ASI_DTWINX:
2052 #ifdef TARGET_SPARC64
2053 {
2054 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2055 TCGv_i128 t = tcg_temp_new_i128();
2056
2057 tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
2058 /*
2059 * Note that LE twinx acts as if each 64-bit register result is
2060 * byte swapped. We perform one 128-bit LE load, so must swap
2061 * the order of the writebacks.
2062 */
2063 if ((mop & MO_BSWAP) == MO_TE) {
2064 tcg_gen_extr_i128_i64(lo, hi, t);
2065 } else {
2066 tcg_gen_extr_i128_i64(hi, lo, t);
2067 }
2068 }
2069 break;
2070 #else
2071 g_assert_not_reached();
2072 #endif
2073
2074 case GET_ASI_DIRECT:
2075 {
2076 TCGv_i64 tmp = tcg_temp_new_i64();
2077
2078 tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
2079
2080 /* Note that LE ldda acts as if each 32-bit register
2081 result is byte swapped. Having just performed one
2082 64-bit bswap, we need now to swap the writebacks. */
2083 if ((da->memop & MO_BSWAP) == MO_TE) {
2084 tcg_gen_extr_i64_tl(lo, hi, tmp);
2085 } else {
2086 tcg_gen_extr_i64_tl(hi, lo, tmp);
2087 }
2088 }
2089 break;
2090
2091 default:
2092 /* ??? In theory we've handled all of the ASIs that are valid
2093 for ldda, and this should raise DAE_invalid_asi. However,
2094 real hardware allows others. This can be seen with e.g.
2095 FreeBSD 10.3 wrt ASI_IC_TAG. */
2096 {
2097 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2098 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2099 TCGv_i64 tmp = tcg_temp_new_i64();
2100
2101 save_state(dc);
2102 gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
2103
2104 /* See above. */
2105 if ((da->memop & MO_BSWAP) == MO_TE) {
2106 tcg_gen_extr_i64_tl(lo, hi, tmp);
2107 } else {
2108 tcg_gen_extr_i64_tl(hi, lo, tmp);
2109 }
2110 }
2111 break;
2112 }
2113
2114 gen_store_gpr(dc, rd, hi);
2115 gen_store_gpr(dc, rd + 1, lo);
2116 }
2117
2118 static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2119 {
2120 TCGv hi = gen_load_gpr(dc, rd);
2121 TCGv lo = gen_load_gpr(dc, rd + 1);
2122
2123 switch (da->type) {
2124 case GET_ASI_EXCP:
2125 break;
2126
2127 case GET_ASI_DTWINX:
2128 #ifdef TARGET_SPARC64
2129 {
2130 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2131 TCGv_i128 t = tcg_temp_new_i128();
2132
2133 /*
2134 * Note that LE twinx acts as if each 64-bit register result is
2135 * byte swapped. We perform one 128-bit LE store, so must swap
2136 * the order of the construction.
2137 */
2138 if ((mop & MO_BSWAP) == MO_TE) {
2139 tcg_gen_concat_i64_i128(t, lo, hi);
2140 } else {
2141 tcg_gen_concat_i64_i128(t, hi, lo);
2142 }
2143 tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
2144 }
2145 break;
2146 #else
2147 g_assert_not_reached();
2148 #endif
2149
2150 case GET_ASI_DIRECT:
2151 {
2152 TCGv_i64 t64 = tcg_temp_new_i64();
2153
2154 /* Note that LE stda acts as if each 32-bit register result is
2155 byte swapped. We will perform one 64-bit LE store, so now
2156 we must swap the order of the construction. */
2157 if ((da->memop & MO_BSWAP) == MO_TE) {
2158 tcg_gen_concat_tl_i64(t64, lo, hi);
2159 } else {
2160 tcg_gen_concat_tl_i64(t64, hi, lo);
2161 }
2162 tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
2163 }
2164 break;
2165
2166 case GET_ASI_BFILL:
2167 assert(TARGET_LONG_BITS == 32);
2168 /* Store 32 bytes of T64 to ADDR. */
2169 /* ??? The original qemu code suggests 8-byte alignment, dropping
2170 the low bits, but the only place I can see this used is in the
2171 Linux kernel with 32 byte alignment, which would make more sense
2172 as a cacheline-style operation. */
2173 {
2174 TCGv_i64 t64 = tcg_temp_new_i64();
2175 TCGv d_addr = tcg_temp_new();
2176 TCGv eight = tcg_constant_tl(8);
2177 int i;
2178
2179 tcg_gen_concat_tl_i64(t64, lo, hi);
2180 tcg_gen_andi_tl(d_addr, addr, -8);
2181 for (i = 0; i < 32; i += 8) {
2182 tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop);
2183 tcg_gen_add_tl(d_addr, d_addr, eight);
2184 }
2185 }
2186 break;
2187
2188 default:
2189 /* ??? In theory we've handled all of the ASIs that are valid
2190 for stda, and this should raise DAE_invalid_asi. */
2191 {
2192 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2193 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2194 TCGv_i64 t64 = tcg_temp_new_i64();
2195
2196 /* See above. */
2197 if ((da->memop & MO_BSWAP) == MO_TE) {
2198 tcg_gen_concat_tl_i64(t64, lo, hi);
2199 } else {
2200 tcg_gen_concat_tl_i64(t64, hi, lo);
2201 }
2202
2203 save_state(dc);
2204 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
2205 }
2206 break;
2207 }
2208 }
2209
2210 static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2211 {
2212 #ifdef TARGET_SPARC64
2213 TCGv_i32 c32, zero, dst, s1, s2;
2214 TCGv_i64 c64 = tcg_temp_new_i64();
2215
2216 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2217 or fold the comparison down to 32 bits and use movcond_i32. Choose
2218 the later. */
2219 c32 = tcg_temp_new_i32();
2220 tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2221 tcg_gen_extrl_i64_i32(c32, c64);
2222
2223 s1 = gen_load_fpr_F(dc, rs);
2224 s2 = gen_load_fpr_F(dc, rd);
2225 dst = gen_dest_fpr_F(dc);
2226 zero = tcg_constant_i32(0);
2227
2228 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2229
2230 gen_store_fpr_F(dc, rd, dst);
2231 #else
2232 qemu_build_not_reached();
2233 #endif
2234 }
2235
2236 static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2237 {
2238 #ifdef TARGET_SPARC64
2239 TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
2240 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
2241 gen_load_fpr_D(dc, rs),
2242 gen_load_fpr_D(dc, rd));
2243 gen_store_fpr_D(dc, rd, dst);
2244 #else
2245 qemu_build_not_reached();
2246 #endif
2247 }
2248
2249 static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2250 {
2251 #ifdef TARGET_SPARC64
2252 int qd = QFPREG(rd);
2253 int qs = QFPREG(rs);
2254 TCGv c2 = tcg_constant_tl(cmp->c2);
2255
2256 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, c2,
2257 cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2258 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, c2,
2259 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2260
2261 gen_update_fprs_dirty(dc, qd);
2262 #else
2263 qemu_build_not_reached();
2264 #endif
2265 }
2266
2267 #ifdef TARGET_SPARC64
2268 static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
2269 {
2270 TCGv_i32 r_tl = tcg_temp_new_i32();
2271
2272 /* load env->tl into r_tl */
2273 tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
2274
2275 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2276 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2277
2278 /* calculate offset to current trap state from env->ts, reuse r_tl */
2279 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2280 tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
2281
2282 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2283 {
2284 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2285 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2286 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2287 }
2288 }
2289 #endif
2290
2291 static int extract_dfpreg(DisasContext *dc, int x)
2292 {
2293 return DFPREG(x);
2294 }
2295
2296 static int extract_qfpreg(DisasContext *dc, int x)
2297 {
2298 return QFPREG(x);
2299 }
2300
2301 /* Include the auto-generated decoder. */
2302 #include "decode-insns.c.inc"
2303
2304 #define TRANS(NAME, AVAIL, FUNC, ...) \
2305 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2306 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2307
2308 #define avail_ALL(C) true
2309 #ifdef TARGET_SPARC64
2310 # define avail_32(C) false
2311 # define avail_ASR17(C) false
2312 # define avail_CASA(C) true
2313 # define avail_DIV(C) true
2314 # define avail_MUL(C) true
2315 # define avail_POWERDOWN(C) false
2316 # define avail_64(C) true
2317 # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
2318 # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
2319 # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1)
2320 # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2)
2321 #else
2322 # define avail_32(C) true
2323 # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
2324 # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA)
2325 # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV)
2326 # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL)
2327 # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2328 # define avail_64(C) false
2329 # define avail_GL(C) false
2330 # define avail_HYPV(C) false
2331 # define avail_VIS1(C) false
2332 # define avail_VIS2(C) false
2333 #endif
2334
2335 /* Default case for non jump instructions. */
2336 static bool advance_pc(DisasContext *dc)
2337 {
2338 TCGLabel *l1;
2339
2340 finishing_insn(dc);
2341
2342 if (dc->npc & 3) {
2343 switch (dc->npc) {
2344 case DYNAMIC_PC:
2345 case DYNAMIC_PC_LOOKUP:
2346 dc->pc = dc->npc;
2347 tcg_gen_mov_tl(cpu_pc, cpu_npc);
2348 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2349 break;
2350
2351 case JUMP_PC:
2352 /* we can do a static jump */
2353 l1 = gen_new_label();
2354 tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
2355
2356 /* jump not taken */
2357 gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
2358
2359 /* jump taken */
2360 gen_set_label(l1);
2361 gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
2362
2363 dc->base.is_jmp = DISAS_NORETURN;
2364 break;
2365
2366 default:
2367 g_assert_not_reached();
2368 }
2369 } else {
2370 dc->pc = dc->npc;
2371 dc->npc = dc->npc + 4;
2372 }
2373 return true;
2374 }
2375
2376 /*
2377 * Major opcodes 00 and 01 -- branches, call, and sethi
2378 */
2379
2380 static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
2381 bool annul, int disp)
2382 {
2383 target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
2384 target_ulong npc;
2385
2386 finishing_insn(dc);
2387
2388 if (cmp->cond == TCG_COND_ALWAYS) {
2389 if (annul) {
2390 dc->pc = dest;
2391 dc->npc = dest + 4;
2392 } else {
2393 gen_mov_pc_npc(dc);
2394 dc->npc = dest;
2395 }
2396 return true;
2397 }
2398
2399 if (cmp->cond == TCG_COND_NEVER) {
2400 npc = dc->npc;
2401 if (npc & 3) {
2402 gen_mov_pc_npc(dc);
2403 if (annul) {
2404 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
2405 }
2406 tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
2407 } else {
2408 dc->pc = npc + (annul ? 4 : 0);
2409 dc->npc = dc->pc + 4;
2410 }
2411 return true;
2412 }
2413
2414 flush_cond(dc);
2415 npc = dc->npc;
2416
2417 if (annul) {
2418 TCGLabel *l1 = gen_new_label();
2419
2420 tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
2421 gen_goto_tb(dc, 0, npc, dest);
2422 gen_set_label(l1);
2423 gen_goto_tb(dc, 1, npc + 4, npc + 8);
2424
2425 dc->base.is_jmp = DISAS_NORETURN;
2426 } else {
2427 if (npc & 3) {
2428 switch (npc) {
2429 case DYNAMIC_PC:
2430 case DYNAMIC_PC_LOOKUP:
2431 tcg_gen_mov_tl(cpu_pc, cpu_npc);
2432 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2433 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
2434 cmp->c1, tcg_constant_tl(cmp->c2),
2435 tcg_constant_tl(dest), cpu_npc);
2436 dc->pc = npc;
2437 break;
2438 default:
2439 g_assert_not_reached();
2440 }
2441 } else {
2442 dc->pc = npc;
2443 dc->npc = JUMP_PC;
2444 dc->jump = *cmp;
2445 dc->jump_pc[0] = dest;
2446 dc->jump_pc[1] = npc + 4;
2447
2448 /* The condition for cpu_cond is always NE -- normalize. */
2449 if (cmp->cond == TCG_COND_NE) {
2450 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
2451 } else {
2452 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
2453 }
2454 dc->cpu_cond_live = true;
2455 }
2456 }
2457 return true;
2458 }
2459
2460 static bool raise_priv(DisasContext *dc)
2461 {
2462 gen_exception(dc, TT_PRIV_INSN);
2463 return true;
2464 }
2465
2466 static bool raise_unimpfpop(DisasContext *dc)
2467 {
2468 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
2469 return true;
2470 }
2471
2472 static bool gen_trap_float128(DisasContext *dc)
2473 {
2474 if (dc->def->features & CPU_FEATURE_FLOAT128) {
2475 return false;
2476 }
2477 return raise_unimpfpop(dc);
2478 }
2479
2480 static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2481 {
2482 DisasCompare cmp;
2483
2484 gen_compare(&cmp, a->cc, a->cond, dc);
2485 return advance_jump_cond(dc, &cmp, a->a, a->i);
2486 }
2487
2488 TRANS(Bicc, ALL, do_bpcc, a)
2489 TRANS(BPcc, 64, do_bpcc, a)
2490
2491 static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
2492 {
2493 DisasCompare cmp;
2494
2495 if (gen_trap_ifnofpu(dc)) {
2496 return true;
2497 }
2498 gen_fcompare(&cmp, a->cc, a->cond);
2499 return advance_jump_cond(dc, &cmp, a->a, a->i);
2500 }
2501
2502 TRANS(FBPfcc, 64, do_fbpfcc, a)
2503 TRANS(FBfcc, ALL, do_fbpfcc, a)
2504
2505 static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2506 {
2507 DisasCompare cmp;
2508
2509 if (!avail_64(dc)) {
2510 return false;
2511 }
2512 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
2513 return false;
2514 }
2515 return advance_jump_cond(dc, &cmp, a->a, a->i);
2516 }
2517
2518 static bool trans_CALL(DisasContext *dc, arg_CALL *a)
2519 {
2520 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
2521
2522 gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
2523 gen_mov_pc_npc(dc);
2524 dc->npc = target;
2525 return true;
2526 }
2527
2528 static bool trans_NCP(DisasContext *dc, arg_NCP *a)
2529 {
2530 /*
2531 * For sparc32, always generate the no-coprocessor exception.
2532 * For sparc64, always generate illegal instruction.
2533 */
2534 #ifdef TARGET_SPARC64
2535 return false;
2536 #else
2537 gen_exception(dc, TT_NCP_INSN);
2538 return true;
2539 #endif
2540 }
2541
2542 static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
2543 {
2544 /* Special-case %g0 because that's the canonical nop. */
2545 if (a->rd) {
2546 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
2547 }
2548 return advance_pc(dc);
2549 }
2550
2551 /*
2552 * Major Opcode 10 -- integer, floating-point, vis, and system insns.
2553 */
2554
2555 static bool do_tcc(DisasContext *dc, int cond, int cc,
2556 int rs1, bool imm, int rs2_or_imm)
2557 {
2558 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
2559 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
2560 DisasCompare cmp;
2561 TCGLabel *lab;
2562 TCGv_i32 trap;
2563
2564 /* Trap never. */
2565 if (cond == 0) {
2566 return advance_pc(dc);
2567 }
2568
2569 /*
2570 * Immediate traps are the most common case. Since this value is
2571 * live across the branch, it really pays to evaluate the constant.
2572 */
2573 if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
2574 trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
2575 } else {
2576 trap = tcg_temp_new_i32();
2577 tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
2578 if (imm) {
2579 tcg_gen_addi_i32(trap, trap, rs2_or_imm);
2580 } else {
2581 TCGv_i32 t2 = tcg_temp_new_i32();
2582 tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
2583 tcg_gen_add_i32(trap, trap, t2);
2584 }
2585 tcg_gen_andi_i32(trap, trap, mask);
2586 tcg_gen_addi_i32(trap, trap, TT_TRAP);
2587 }
2588
2589 finishing_insn(dc);
2590
2591 /* Trap always. */
2592 if (cond == 8) {
2593 save_state(dc);
2594 gen_helper_raise_exception(tcg_env, trap);
2595 dc->base.is_jmp = DISAS_NORETURN;
2596 return true;
2597 }
2598
2599 /* Conditional trap. */
2600 flush_cond(dc);
2601 lab = delay_exceptionv(dc, trap);
2602 gen_compare(&cmp, cc, cond, dc);
2603 tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
2604
2605 return advance_pc(dc);
2606 }
2607
2608 static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
2609 {
2610 if (avail_32(dc) && a->cc) {
2611 return false;
2612 }
2613 return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
2614 }
2615
2616 static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
2617 {
2618 if (avail_64(dc)) {
2619 return false;
2620 }
2621 return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
2622 }
2623
2624 static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
2625 {
2626 if (avail_32(dc)) {
2627 return false;
2628 }
2629 return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
2630 }
2631
2632 static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2633 {
2634 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2635 return advance_pc(dc);
2636 }
2637
2638 static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2639 {
2640 if (avail_32(dc)) {
2641 return false;
2642 }
2643 if (a->mmask) {
2644 /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2645 tcg_gen_mb(a->mmask | TCG_BAR_SC);
2646 }
2647 if (a->cmask) {
2648 /* For #Sync, etc, end the TB to recognize interrupts. */
2649 dc->base.is_jmp = DISAS_EXIT;
2650 }
2651 return advance_pc(dc);
2652 }
2653
2654 static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2655 TCGv (*func)(DisasContext *, TCGv))
2656 {
2657 if (!priv) {
2658 return raise_priv(dc);
2659 }
2660 gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2661 return advance_pc(dc);
2662 }
2663
2664 static TCGv do_rdy(DisasContext *dc, TCGv dst)
2665 {
2666 return cpu_y;
2667 }
2668
2669 static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2670 {
2671 /*
2672 * TODO: Need a feature bit for sparcv8. In the meantime, treat all
2673 * 32-bit cpus like sparcv7, which ignores the rs1 field.
2674 * This matches after all other ASR, so Leon3 Asr17 is handled first.
2675 */
2676 if (avail_64(dc) && a->rs1 != 0) {
2677 return false;
2678 }
2679 return do_rd_special(dc, true, a->rd, do_rdy);
2680 }
2681
2682 static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2683 {
2684 uint32_t val;
2685
2686 /*
2687 * TODO: There are many more fields to be filled,
2688 * some of which are writable.
2689 */
2690 val = dc->def->nwindows - 1; /* [4:0] NWIN */
2691 val |= 1 << 8; /* [8] V8 */
2692
2693 return tcg_constant_tl(val);
2694 }
2695
2696 TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2697
2698 static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2699 {
2700 gen_helper_rdccr(dst, tcg_env);
2701 return dst;
2702 }
2703
2704 TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2705
2706 static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2707 {
2708 #ifdef TARGET_SPARC64
2709 return tcg_constant_tl(dc->asi);
2710 #else
2711 qemu_build_not_reached();
2712 #endif
2713 }
2714
2715 TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2716
2717 static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2718 {
2719 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2720
2721 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2722 if (translator_io_start(&dc->base)) {
2723 dc->base.is_jmp = DISAS_EXIT;
2724 }
2725 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2726 tcg_constant_i32(dc->mem_idx));
2727 return dst;
2728 }
2729
2730 /* TODO: non-priv access only allowed when enabled. */
2731 TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2732
2733 static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2734 {
2735 return tcg_constant_tl(address_mask_i(dc, dc->pc));
2736 }
2737
2738 TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2739
2740 static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2741 {
2742 tcg_gen_ext_i32_tl(dst, cpu_fprs);
2743 return dst;
2744 }
2745
2746 TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2747
2748 static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2749 {
2750 gen_trap_ifnofpu(dc);
2751 return cpu_gsr;
2752 }
2753
2754 TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2755
2756 static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2757 {
2758 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2759 return dst;
2760 }
2761
2762 TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2763
2764 static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2765 {
2766 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2767 return dst;
2768 }
2769
2770 /* TODO: non-priv access only allowed when enabled. */
2771 TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2772
2773 static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2774 {
2775 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2776
2777 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2778 if (translator_io_start(&dc->base)) {
2779 dc->base.is_jmp = DISAS_EXIT;
2780 }
2781 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2782 tcg_constant_i32(dc->mem_idx));
2783 return dst;
2784 }
2785
2786 /* TODO: non-priv access only allowed when enabled. */
2787 TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2788
2789 static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2790 {
2791 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2792 return dst;
2793 }
2794
2795 /* TODO: supervisor access only allowed when enabled by hypervisor. */
2796 TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2797
2798 /*
2799 * UltraSPARC-T1 Strand status.
2800 * HYPV check maybe not enough, UA2005 & UA2007 describe
2801 * this ASR as impl. dep
2802 */
2803 static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2804 {
2805 return tcg_constant_tl(1);
2806 }
2807
2808 TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
2809
2810 static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
2811 {
2812 gen_helper_rdpsr(dst, tcg_env);
2813 return dst;
2814 }
2815
2816 TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
2817
2818 static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
2819 {
2820 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
2821 return dst;
2822 }
2823
2824 TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
2825
2826 static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
2827 {
2828 TCGv_i32 tl = tcg_temp_new_i32();
2829 TCGv_ptr tp = tcg_temp_new_ptr();
2830
2831 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
2832 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
2833 tcg_gen_shli_i32(tl, tl, 3);
2834 tcg_gen_ext_i32_ptr(tp, tl);
2835 tcg_gen_add_ptr(tp, tp, tcg_env);
2836
2837 tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
2838 return dst;
2839 }
2840
2841 TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
2842
2843 static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
2844 {
2845 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
2846 return dst;
2847 }
2848
2849 TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
2850
2851 static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
2852 {
2853 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
2854 return dst;
2855 }
2856
2857 TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
2858
2859 static TCGv do_rdhver(DisasContext *dc, TCGv dst)
2860 {
2861 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
2862 return dst;
2863 }
2864
2865 TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
2866
2867 static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
2868 {
2869 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
2870 return dst;
2871 }
2872
2873 TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
2874 do_rdhstick_cmpr)
2875
2876 static TCGv do_rdwim(DisasContext *dc, TCGv dst)
2877 {
2878 tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
2879 return dst;
2880 }
2881
2882 TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
2883
2884 static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
2885 {
2886 #ifdef TARGET_SPARC64
2887 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2888
2889 gen_load_trap_state_at_tl(r_tsptr);
2890 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
2891 return dst;
2892 #else
2893 qemu_build_not_reached();
2894 #endif
2895 }
2896
2897 TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
2898
2899 static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
2900 {
2901 #ifdef TARGET_SPARC64
2902 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2903
2904 gen_load_trap_state_at_tl(r_tsptr);
2905 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
2906 return dst;
2907 #else
2908 qemu_build_not_reached();
2909 #endif
2910 }
2911
2912 TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
2913
2914 static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
2915 {
2916 #ifdef TARGET_SPARC64
2917 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2918
2919 gen_load_trap_state_at_tl(r_tsptr);
2920 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
2921 return dst;
2922 #else
2923 qemu_build_not_reached();
2924 #endif
2925 }
2926
2927 TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
2928
2929 static TCGv do_rdtt(DisasContext *dc, TCGv dst)
2930 {
2931 #ifdef TARGET_SPARC64
2932 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2933
2934 gen_load_trap_state_at_tl(r_tsptr);
2935 tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
2936 return dst;
2937 #else
2938 qemu_build_not_reached();
2939 #endif
2940 }
2941
2942 TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
2943 TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
2944
2945 static TCGv do_rdtba(DisasContext *dc, TCGv dst)
2946 {
2947 return cpu_tbr;
2948 }
2949
2950 TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
2951 TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
2952
2953 static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
2954 {
2955 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
2956 return dst;
2957 }
2958
2959 TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
2960
2961 static TCGv do_rdtl(DisasContext *dc, TCGv dst)
2962 {
2963 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
2964 return dst;
2965 }
2966
2967 TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
2968
2969 static TCGv do_rdpil(DisasContext *dc, TCGv dst)
2970 {
2971 tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
2972 return dst;
2973 }
2974
2975 TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
2976
2977 static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
2978 {
2979 gen_helper_rdcwp(dst, tcg_env);
2980 return dst;
2981 }
2982
2983 TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
2984
2985 static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
2986 {
2987 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
2988 return dst;
2989 }
2990
2991 TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
2992
2993 static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
2994 {
2995 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
2996 return dst;
2997 }
2998
2999 TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
3000 do_rdcanrestore)
3001
3002 static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
3003 {
3004 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
3005 return dst;
3006 }
3007
3008 TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
3009
3010 static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
3011 {
3012 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
3013 return dst;
3014 }
3015
3016 TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
3017
3018 static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
3019 {
3020 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
3021 return dst;
3022 }
3023
3024 TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
3025
3026 static TCGv do_rdgl(DisasContext *dc, TCGv dst)
3027 {
3028 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
3029 return dst;
3030 }
3031
3032 TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
3033
3034 /* UA2005 strand status */
3035 static TCGv do_rdssr(DisasContext *dc, TCGv dst)
3036 {
3037 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
3038 return dst;
3039 }
3040
3041 TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
3042
3043 static TCGv do_rdver(DisasContext *dc, TCGv dst)
3044 {
3045 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
3046 return dst;
3047 }
3048
3049 TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
3050
3051 static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
3052 {
3053 if (avail_64(dc)) {
3054 gen_helper_flushw(tcg_env);
3055 return advance_pc(dc);
3056 }
3057 return false;
3058 }
3059
3060 static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
3061 void (*func)(DisasContext *, TCGv))
3062 {
3063 TCGv src;
3064
3065 /* For simplicity, we under-decoded the rs2 form. */
3066 if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
3067 return false;
3068 }
3069 if (!priv) {
3070 return raise_priv(dc);
3071 }
3072
3073 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
3074 src = tcg_constant_tl(a->rs2_or_imm);
3075 } else {
3076 TCGv src1 = gen_load_gpr(dc, a->rs1);
3077 if (a->rs2_or_imm == 0) {
3078 src = src1;
3079 } else {
3080 src = tcg_temp_new();
3081 if (a->imm) {
3082 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
3083 } else {
3084 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
3085 }
3086 }
3087 }
3088 func(dc, src);
3089 return advance_pc(dc);
3090 }
3091
3092 static void do_wry(DisasContext *dc, TCGv src)
3093 {
3094 tcg_gen_ext32u_tl(cpu_y, src);
3095 }
3096
3097 TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
3098
3099 static void do_wrccr(DisasContext *dc, TCGv src)
3100 {
3101 gen_helper_wrccr(tcg_env, src);
3102 }
3103
3104 TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
3105
3106 static void do_wrasi(DisasContext *dc, TCGv src)
3107 {
3108 TCGv tmp = tcg_temp_new();
3109
3110 tcg_gen_ext8u_tl(tmp, src);
3111 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
3112 /* End TB to notice changed ASI. */
3113 dc->base.is_jmp = DISAS_EXIT;
3114 }
3115
3116 TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
3117
3118 static void do_wrfprs(DisasContext *dc, TCGv src)
3119 {
3120 #ifdef TARGET_SPARC64
3121 tcg_gen_trunc_tl_i32(cpu_fprs, src);
3122 dc->fprs_dirty = 0;
3123 dc->base.is_jmp = DISAS_EXIT;
3124 #else
3125 qemu_build_not_reached();
3126 #endif
3127 }
3128
3129 TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
3130
3131 static void do_wrgsr(DisasContext *dc, TCGv src)
3132 {
3133 gen_trap_ifnofpu(dc);
3134 tcg_gen_mov_tl(cpu_gsr, src);
3135 }
3136
3137 TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
3138
3139 static void do_wrsoftint_set(DisasContext *dc, TCGv src)
3140 {
3141 gen_helper_set_softint(tcg_env, src);
3142 }
3143
3144 TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
3145
3146 static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
3147 {
3148 gen_helper_clear_softint(tcg_env, src);
3149 }
3150
3151 TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
3152
3153 static void do_wrsoftint(DisasContext *dc, TCGv src)
3154 {
3155 gen_helper_write_softint(tcg_env, src);
3156 }
3157
3158 TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
3159
3160 static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
3161 {
3162 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3163
3164 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
3165 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3166 translator_io_start(&dc->base);
3167 gen_helper_tick_set_limit(r_tickptr, src);
3168 /* End TB to handle timer interrupt */
3169 dc->base.is_jmp = DISAS_EXIT;
3170 }
3171
3172 TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
3173
3174 static void do_wrstick(DisasContext *dc, TCGv src)
3175 {
3176 #ifdef TARGET_SPARC64
3177 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3178
3179 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
3180 translator_io_start(&dc->base);
3181 gen_helper_tick_set_count(r_tickptr, src);
3182 /* End TB to handle timer interrupt */
3183 dc->base.is_jmp = DISAS_EXIT;
3184 #else
3185 qemu_build_not_reached();
3186 #endif
3187 }
3188
3189 TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
3190
3191 static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
3192 {
3193 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3194
3195 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
3196 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
3197 translator_io_start(&dc->base);
3198 gen_helper_tick_set_limit(r_tickptr, src);
3199 /* End TB to handle timer interrupt */
3200 dc->base.is_jmp = DISAS_EXIT;
3201 }
3202
3203 TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
3204
3205 static void do_wrpowerdown(DisasContext *dc, TCGv src)
3206 {
3207 finishing_insn(dc);
3208 save_state(dc);
3209 gen_helper_power_down(tcg_env);
3210 }
3211
3212 TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
3213
3214 static void do_wrpsr(DisasContext *dc, TCGv src)
3215 {
3216 gen_helper_wrpsr(tcg_env, src);
3217 dc->base.is_jmp = DISAS_EXIT;
3218 }
3219
3220 TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
3221
3222 static void do_wrwim(DisasContext *dc, TCGv src)
3223 {
3224 target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
3225 TCGv tmp = tcg_temp_new();
3226
3227 tcg_gen_andi_tl(tmp, src, mask);
3228 tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
3229 }
3230
3231 TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
3232
3233 static void do_wrtpc(DisasContext *dc, TCGv src)
3234 {
3235 #ifdef TARGET_SPARC64
3236 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3237
3238 gen_load_trap_state_at_tl(r_tsptr);
3239 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
3240 #else
3241 qemu_build_not_reached();
3242 #endif
3243 }
3244
3245 TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
3246
3247 static void do_wrtnpc(DisasContext *dc, TCGv src)
3248 {
3249 #ifdef TARGET_SPARC64
3250 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3251
3252 gen_load_trap_state_at_tl(r_tsptr);
3253 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
3254 #else
3255 qemu_build_not_reached();
3256 #endif
3257 }
3258
3259 TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
3260
3261 static void do_wrtstate(DisasContext *dc, TCGv src)
3262 {
3263 #ifdef TARGET_SPARC64
3264 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3265
3266 gen_load_trap_state_at_tl(r_tsptr);
3267 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
3268 #else
3269 qemu_build_not_reached();
3270 #endif
3271 }
3272
3273 TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
3274
3275 static void do_wrtt(DisasContext *dc, TCGv src)
3276 {
3277 #ifdef TARGET_SPARC64
3278 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3279
3280 gen_load_trap_state_at_tl(r_tsptr);
3281 tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
3282 #else
3283 qemu_build_not_reached();
3284 #endif
3285 }
3286
3287 TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
3288
3289 static void do_wrtick(DisasContext *dc, TCGv src)
3290 {
3291 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3292
3293 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3294 translator_io_start(&dc->base);
3295 gen_helper_tick_set_count(r_tickptr, src);
3296 /* End TB to handle timer interrupt */
3297 dc->base.is_jmp = DISAS_EXIT;
3298 }
3299
3300 TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
3301
3302 static void do_wrtba(DisasContext *dc, TCGv src)
3303 {
3304 tcg_gen_mov_tl(cpu_tbr, src);
3305 }
3306
3307 TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
3308
3309 static void do_wrpstate(DisasContext *dc, TCGv src)
3310 {
3311 save_state(dc);
3312 if (translator_io_start(&dc->base)) {
3313 dc->base.is_jmp = DISAS_EXIT;
3314 }
3315 gen_helper_wrpstate(tcg_env, src);
3316 dc->npc = DYNAMIC_PC;
3317 }
3318
3319 TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
3320
3321 static void do_wrtl(DisasContext *dc, TCGv src)
3322 {
3323 save_state(dc);
3324 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
3325 dc->npc = DYNAMIC_PC;
3326 }
3327
3328 TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
3329
3330 static void do_wrpil(DisasContext *dc, TCGv src)
3331 {
3332 if (translator_io_start(&dc->base)) {
3333 dc->base.is_jmp = DISAS_EXIT;
3334 }
3335 gen_helper_wrpil(tcg_env, src);
3336 }
3337
3338 TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
3339
3340 static void do_wrcwp(DisasContext *dc, TCGv src)
3341 {
3342 gen_helper_wrcwp(tcg_env, src);
3343 }
3344
3345 TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
3346
3347 static void do_wrcansave(DisasContext *dc, TCGv src)
3348 {
3349 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
3350 }
3351
3352 TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
3353
3354 static void do_wrcanrestore(DisasContext *dc, TCGv src)
3355 {
3356 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
3357 }
3358
3359 TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
3360
3361 static void do_wrcleanwin(DisasContext *dc, TCGv src)
3362 {
3363 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
3364 }
3365
3366 TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
3367
3368 static void do_wrotherwin(DisasContext *dc, TCGv src)
3369 {
3370 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
3371 }
3372
3373 TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
3374
3375 static void do_wrwstate(DisasContext *dc, TCGv src)
3376 {
3377 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
3378 }
3379
3380 TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
3381
3382 static void do_wrgl(DisasContext *dc, TCGv src)
3383 {
3384 gen_helper_wrgl(tcg_env, src);
3385 }
3386
3387 TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
3388
3389 /* UA2005 strand status */
3390 static void do_wrssr(DisasContext *dc, TCGv src)
3391 {
3392 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
3393 }
3394
3395 TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
3396
3397 TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3398
3399 static void do_wrhpstate(DisasContext *dc, TCGv src)
3400 {
3401 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3402 dc->base.is_jmp = DISAS_EXIT;
3403 }
3404
3405 TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3406
3407 static void do_wrhtstate(DisasContext *dc, TCGv src)
3408 {
3409 TCGv_i32 tl = tcg_temp_new_i32();
3410 TCGv_ptr tp = tcg_temp_new_ptr();
3411
3412 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3413 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3414 tcg_gen_shli_i32(tl, tl, 3);
3415 tcg_gen_ext_i32_ptr(tp, tl);
3416 tcg_gen_add_ptr(tp, tp, tcg_env);
3417
3418 tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3419 }
3420
3421 TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3422
3423 static void do_wrhintp(DisasContext *dc, TCGv src)
3424 {
3425 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
3426 }
3427
3428 TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3429
3430 static void do_wrhtba(DisasContext *dc, TCGv src)
3431 {
3432 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
3433 }
3434
3435 TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3436
3437 static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3438 {
3439 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3440
3441 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
3442 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3443 translator_io_start(&dc->base);
3444 gen_helper_tick_set_limit(r_tickptr, src);
3445 /* End TB to handle timer interrupt */
3446 dc->base.is_jmp = DISAS_EXIT;
3447 }
3448
3449 TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3450 do_wrhstick_cmpr)
3451
3452 static bool do_saved_restored(DisasContext *dc, bool saved)
3453 {
3454 if (!supervisor(dc)) {
3455 return raise_priv(dc);
3456 }
3457 if (saved) {
3458 gen_helper_saved(tcg_env);
3459 } else {
3460 gen_helper_restored(tcg_env);
3461 }
3462 return advance_pc(dc);
3463 }
3464
3465 TRANS(SAVED, 64, do_saved_restored, true)
3466 TRANS(RESTORED, 64, do_saved_restored, false)
3467
3468 static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3469 {
3470 return advance_pc(dc);
3471 }
3472
3473 /*
3474 * TODO: Need a feature bit for sparcv8.
3475 * In the meantime, treat all 32-bit cpus like sparcv7.
3476 */
3477 TRANS(NOP_v7, 32, trans_NOP, a)
3478 TRANS(NOP_v9, 64, trans_NOP, a)
3479
3480 static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
3481 void (*func)(TCGv, TCGv, TCGv),
3482 void (*funci)(TCGv, TCGv, target_long),
3483 bool logic_cc)
3484 {
3485 TCGv dst, src1;
3486
3487 /* For simplicity, we under-decoded the rs2 form. */
3488 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3489 return false;
3490 }
3491
3492 if (logic_cc) {
3493 dst = cpu_cc_N;
3494 } else {
3495 dst = gen_dest_gpr(dc, a->rd);
3496 }
3497 src1 = gen_load_gpr(dc, a->rs1);
3498
3499 if (a->imm || a->rs2_or_imm == 0) {
3500 if (funci) {
3501 funci(dst, src1, a->rs2_or_imm);
3502 } else {
3503 func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3504 }
3505 } else {
3506 func(dst, src1, cpu_regs[a->rs2_or_imm]);
3507 }
3508
3509 if (logic_cc) {
3510 if (TARGET_LONG_BITS == 64) {
3511 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
3512 tcg_gen_movi_tl(cpu_icc_C, 0);
3513 }
3514 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
3515 tcg_gen_movi_tl(cpu_cc_C, 0);
3516 tcg_gen_movi_tl(cpu_cc_V, 0);
3517 }
3518
3519 gen_store_gpr(dc, a->rd, dst);
3520 return advance_pc(dc);
3521 }
3522
3523 static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
3524 void (*func)(TCGv, TCGv, TCGv),
3525 void (*funci)(TCGv, TCGv, target_long),
3526 void (*func_cc)(TCGv, TCGv, TCGv))
3527 {
3528 if (a->cc) {
3529 return do_arith_int(dc, a, func_cc, NULL, false);
3530 }
3531 return do_arith_int(dc, a, func, funci, false);
3532 }
3533
3534 static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3535 void (*func)(TCGv, TCGv, TCGv),
3536 void (*funci)(TCGv, TCGv, target_long))
3537 {
3538 return do_arith_int(dc, a, func, funci, a->cc);
3539 }
3540
3541 TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3542 TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3543 TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3544 TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
3545
3546 TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3547 TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3548 TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3549 TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
3550
3551 TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3552 TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3553 TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3554 TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3555 TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3556
3557 TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
3558 TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3559 TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
3560 TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
3561
3562 TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
3563 TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
3564
3565 /* TODO: Should have feature bit -- comes in with UltraSparc T2. */
3566 TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
3567
3568 static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3569 {
3570 /* OR with %g0 is the canonical alias for MOV. */
3571 if (!a->cc && a->rs1 == 0) {
3572 if (a->imm || a->rs2_or_imm == 0) {
3573 gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3574 } else if (a->rs2_or_imm & ~0x1f) {
3575 /* For simplicity, we under-decoded the rs2 form. */
3576 return false;
3577 } else {
3578 gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3579 }
3580 return advance_pc(dc);
3581 }
3582 return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3583 }
3584
3585 static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
3586 {
3587 TCGv_i64 t1, t2;
3588 TCGv dst;
3589
3590 if (!avail_DIV(dc)) {
3591 return false;
3592 }
3593 /* For simplicity, we under-decoded the rs2 form. */
3594 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3595 return false;
3596 }
3597
3598 if (unlikely(a->rs2_or_imm == 0)) {
3599 gen_exception(dc, TT_DIV_ZERO);
3600 return true;
3601 }
3602
3603 if (a->imm) {
3604 t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
3605 } else {
3606 TCGLabel *lab;
3607 TCGv_i32 n2;
3608
3609 finishing_insn(dc);
3610 flush_cond(dc);
3611
3612 n2 = tcg_temp_new_i32();
3613 tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
3614
3615 lab = delay_exception(dc, TT_DIV_ZERO);
3616 tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
3617
3618 t2 = tcg_temp_new_i64();
3619 #ifdef TARGET_SPARC64
3620 tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
3621 #else
3622 tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
3623 #endif
3624 }
3625
3626 t1 = tcg_temp_new_i64();
3627 tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
3628
3629 tcg_gen_divu_i64(t1, t1, t2);
3630 tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
3631
3632 dst = gen_dest_gpr(dc, a->rd);
3633 tcg_gen_trunc_i64_tl(dst, t1);
3634 gen_store_gpr(dc, a->rd, dst);
3635 return advance_pc(dc);
3636 }
3637
3638 static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3639 {
3640 TCGv dst, src1, src2;
3641
3642 if (!avail_64(dc)) {
3643 return false;
3644 }
3645 /* For simplicity, we under-decoded the rs2 form. */
3646 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3647 return false;
3648 }
3649
3650 if (unlikely(a->rs2_or_imm == 0)) {
3651 gen_exception(dc, TT_DIV_ZERO);
3652 return true;
3653 }
3654
3655 if (a->imm) {
3656 src2 = tcg_constant_tl(a->rs2_or_imm);
3657 } else {
3658 TCGLabel *lab;
3659
3660 finishing_insn(dc);
3661 flush_cond(dc);
3662
3663 lab = delay_exception(dc, TT_DIV_ZERO);
3664 src2 = cpu_regs[a->rs2_or_imm];
3665 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3666 }
3667
3668 dst = gen_dest_gpr(dc, a->rd);
3669 src1 = gen_load_gpr(dc, a->rs1);
3670
3671 tcg_gen_divu_tl(dst, src1, src2);
3672 gen_store_gpr(dc, a->rd, dst);
3673 return advance_pc(dc);
3674 }
3675
3676 static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3677 {
3678 TCGv dst, src1, src2;
3679
3680 if (!avail_64(dc)) {
3681 return false;
3682 }
3683 /* For simplicity, we under-decoded the rs2 form. */
3684 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3685 return false;
3686 }
3687
3688 if (unlikely(a->rs2_or_imm == 0)) {
3689 gen_exception(dc, TT_DIV_ZERO);
3690 return true;
3691 }
3692
3693 dst = gen_dest_gpr(dc, a->rd);
3694 src1 = gen_load_gpr(dc, a->rs1);
3695
3696 if (a->imm) {
3697 if (unlikely(a->rs2_or_imm == -1)) {
3698 tcg_gen_neg_tl(dst, src1);
3699 gen_store_gpr(dc, a->rd, dst);
3700 return advance_pc(dc);
3701 }
3702 src2 = tcg_constant_tl(a->rs2_or_imm);
3703 } else {
3704 TCGLabel *lab;
3705 TCGv t1, t2;
3706
3707 finishing_insn(dc);
3708 flush_cond(dc);
3709
3710 lab = delay_exception(dc, TT_DIV_ZERO);
3711 src2 = cpu_regs[a->rs2_or_imm];
3712 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3713
3714 /*
3715 * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3716 * Set SRC2 to 1 as a new divisor, to produce the correct result.
3717 */
3718 t1 = tcg_temp_new();
3719 t2 = tcg_temp_new();
3720 tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3721 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3722 tcg_gen_and_tl(t1, t1, t2);
3723 tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3724 tcg_constant_tl(1), src2);
3725 src2 = t1;
3726 }
3727
3728 tcg_gen_div_tl(dst, src1, src2);
3729 gen_store_gpr(dc, a->rd, dst);
3730 return advance_pc(dc);
3731 }
3732
3733 static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
3734 int width, bool cc, bool left)
3735 {
3736 TCGv dst, s1, s2, lo1, lo2;
3737 uint64_t amask, tabl, tabr;
3738 int shift, imask, omask;
3739
3740 dst = gen_dest_gpr(dc, a->rd);
3741 s1 = gen_load_gpr(dc, a->rs1);
3742 s2 = gen_load_gpr(dc, a->rs2);
3743
3744 if (cc) {
3745 gen_op_subcc(cpu_cc_N, s1, s2);
3746 }
3747
3748 /*
3749 * Theory of operation: there are two tables, left and right (not to
3750 * be confused with the left and right versions of the opcode). These
3751 * are indexed by the low 3 bits of the inputs. To make things "easy",
3752 * these tables are loaded into two constants, TABL and TABR below.
3753 * The operation index = (input & imask) << shift calculates the index
3754 * into the constant, while val = (table >> index) & omask calculates
3755 * the value we're looking for.
3756 */
3757 switch (width) {
3758 case 8:
3759 imask = 0x7;
3760 shift = 3;
3761 omask = 0xff;
3762 if (left) {
3763 tabl = 0x80c0e0f0f8fcfeffULL;
3764 tabr = 0xff7f3f1f0f070301ULL;
3765 } else {
3766 tabl = 0x0103070f1f3f7fffULL;
3767 tabr = 0xfffefcf8f0e0c080ULL;
3768 }
3769 break;
3770 case 16:
3771 imask = 0x6;
3772 shift = 1;
3773 omask = 0xf;
3774 if (left) {
3775 tabl = 0x8cef;
3776 tabr = 0xf731;
3777 } else {
3778 tabl = 0x137f;
3779 tabr = 0xfec8;
3780 }
3781 break;
3782 case 32:
3783 imask = 0x4;
3784 shift = 0;
3785 omask = 0x3;
3786 if (left) {
3787 tabl = (2 << 2) | 3;
3788 tabr = (3 << 2) | 1;
3789 } else {
3790 tabl = (1 << 2) | 3;
3791 tabr = (3 << 2) | 2;
3792 }
3793 break;
3794 default:
3795 abort();
3796 }
3797
3798 lo1 = tcg_temp_new();
3799 lo2 = tcg_temp_new();
3800 tcg_gen_andi_tl(lo1, s1, imask);
3801 tcg_gen_andi_tl(lo2, s2, imask);
3802 tcg_gen_shli_tl(lo1, lo1, shift);
3803 tcg_gen_shli_tl(lo2, lo2, shift);
3804
3805 tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1);
3806 tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2);
3807 tcg_gen_andi_tl(lo1, lo1, omask);
3808 tcg_gen_andi_tl(lo2, lo2, omask);
3809
3810 amask = address_mask_i(dc, -8);
3811 tcg_gen_andi_tl(s1, s1, amask);
3812 tcg_gen_andi_tl(s2, s2, amask);
3813
3814 /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
3815 tcg_gen_and_tl(lo2, lo2, lo1);
3816 tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2);
3817
3818 gen_store_gpr(dc, a->rd, dst);
3819 return advance_pc(dc);
3820 }
3821
3822 TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
3823 TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
3824 TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
3825 TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
3826 TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
3827 TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
3828
3829 TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
3830 TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
3831 TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
3832 TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
3833 TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
3834 TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
3835
3836 static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
3837 void (*func)(TCGv, TCGv, TCGv))
3838 {
3839 TCGv dst = gen_dest_gpr(dc, a->rd);
3840 TCGv src1 = gen_load_gpr(dc, a->rs1);
3841 TCGv src2 = gen_load_gpr(dc, a->rs2);
3842
3843 func(dst, src1, src2);
3844 gen_store_gpr(dc, a->rd, dst);
3845 return advance_pc(dc);
3846 }
3847
3848 TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
3849 TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
3850 TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
3851
3852 static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
3853 {
3854 #ifdef TARGET_SPARC64
3855 TCGv tmp = tcg_temp_new();
3856
3857 tcg_gen_add_tl(tmp, s1, s2);
3858 tcg_gen_andi_tl(dst, tmp, -8);
3859 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
3860 #else
3861 g_assert_not_reached();
3862 #endif
3863 }
3864
3865 static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
3866 {
3867 #ifdef TARGET_SPARC64
3868 TCGv tmp = tcg_temp_new();
3869
3870 tcg_gen_add_tl(tmp, s1, s2);
3871 tcg_gen_andi_tl(dst, tmp, -8);
3872 tcg_gen_neg_tl(tmp, tmp);
3873 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
3874 #else
3875 g_assert_not_reached();
3876 #endif
3877 }
3878
3879 TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
3880 TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
3881
3882 static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
3883 {
3884 #ifdef TARGET_SPARC64
3885 tcg_gen_add_tl(dst, s1, s2);
3886 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
3887 #else
3888 g_assert_not_reached();
3889 #endif
3890 }
3891
3892 TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
3893
3894 static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
3895 {
3896 TCGv dst, src1, src2;
3897
3898 /* Reject 64-bit shifts for sparc32. */
3899 if (avail_32(dc) && a->x) {
3900 return false;
3901 }
3902
3903 src2 = tcg_temp_new();
3904 tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
3905 src1 = gen_load_gpr(dc, a->rs1);
3906 dst = gen_dest_gpr(dc, a->rd);
3907
3908 if (l) {
3909 tcg_gen_shl_tl(dst, src1, src2);
3910 if (!a->x) {
3911 tcg_gen_ext32u_tl(dst, dst);
3912 }
3913 } else if (u) {
3914 if (!a->x) {
3915 tcg_gen_ext32u_tl(dst, src1);
3916 src1 = dst;
3917 }
3918 tcg_gen_shr_tl(dst, src1, src2);
3919 } else {
3920 if (!a->x) {
3921 tcg_gen_ext32s_tl(dst, src1);
3922 src1 = dst;
3923 }
3924 tcg_gen_sar_tl(dst, src1, src2);
3925 }
3926 gen_store_gpr(dc, a->rd, dst);
3927 return advance_pc(dc);
3928 }
3929
3930 TRANS(SLL_r, ALL, do_shift_r, a, true, true)
3931 TRANS(SRL_r, ALL, do_shift_r, a, false, true)
3932 TRANS(SRA_r, ALL, do_shift_r, a, false, false)
3933
3934 static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
3935 {
3936 TCGv dst, src1;
3937
3938 /* Reject 64-bit shifts for sparc32. */
3939 if (avail_32(dc) && (a->x || a->i >= 32)) {
3940 return false;
3941 }
3942
3943 src1 = gen_load_gpr(dc, a->rs1);
3944 dst = gen_dest_gpr(dc, a->rd);
3945
3946 if (avail_32(dc) || a->x) {
3947 if (l) {
3948 tcg_gen_shli_tl(dst, src1, a->i);
3949 } else if (u) {
3950 tcg_gen_shri_tl(dst, src1, a->i);
3951 } else {
3952 tcg_gen_sari_tl(dst, src1, a->i);
3953 }
3954 } else {
3955 if (l) {
3956 tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
3957 } else if (u) {
3958 tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
3959 } else {
3960 tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
3961 }
3962 }
3963 gen_store_gpr(dc, a->rd, dst);
3964 return advance_pc(dc);
3965 }
3966
3967 TRANS(SLL_i, ALL, do_shift_i, a, true, true)
3968 TRANS(SRL_i, ALL, do_shift_i, a, false, true)
3969 TRANS(SRA_i, ALL, do_shift_i, a, false, false)
3970
3971 static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
3972 {
3973 /* For simplicity, we under-decoded the rs2 form. */
3974 if (!imm && rs2_or_imm & ~0x1f) {
3975 return NULL;
3976 }
3977 if (imm || rs2_or_imm == 0) {
3978 return tcg_constant_tl(rs2_or_imm);
3979 } else {
3980 return cpu_regs[rs2_or_imm];
3981 }
3982 }
3983
3984 static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
3985 {
3986 TCGv dst = gen_load_gpr(dc, rd);
3987 TCGv c2 = tcg_constant_tl(cmp->c2);
3988
3989 tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
3990 gen_store_gpr(dc, rd, dst);
3991 return advance_pc(dc);
3992 }
3993
3994 static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
3995 {
3996 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3997 DisasCompare cmp;
3998
3999 if (src2 == NULL) {
4000 return false;
4001 }
4002 gen_compare(&cmp, a->cc, a->cond, dc);
4003 return do_mov_cond(dc, &cmp, a->rd, src2);
4004 }
4005
4006 static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
4007 {
4008 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4009 DisasCompare cmp;
4010
4011 if (src2 == NULL) {
4012 return false;
4013 }
4014 gen_fcompare(&cmp, a->cc, a->cond);
4015 return do_mov_cond(dc, &cmp, a->rd, src2);
4016 }
4017
4018 static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
4019 {
4020 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4021 DisasCompare cmp;
4022
4023 if (src2 == NULL) {
4024 return false;
4025 }
4026 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
4027 return false;
4028 }
4029 return do_mov_cond(dc, &cmp, a->rd, src2);
4030 }
4031
4032 static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
4033 bool (*func)(DisasContext *dc, int rd, TCGv src))
4034 {
4035 TCGv src1, sum;
4036
4037 /* For simplicity, we under-decoded the rs2 form. */
4038 if (!a->imm && a->rs2_or_imm & ~0x1f) {
4039 return false;
4040 }
4041
4042 /*
4043 * Always load the sum into a new temporary.
4044 * This is required to capture the value across a window change,
4045 * e.g. SAVE and RESTORE, and may be optimized away otherwise.
4046 */
4047 sum = tcg_temp_new();
4048 src1 = gen_load_gpr(dc, a->rs1);
4049 if (a->imm || a->rs2_or_imm == 0) {
4050 tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
4051 } else {
4052 tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
4053 }
4054 return func(dc, a->rd, sum);
4055 }
4056
4057 static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
4058 {
4059 /*
4060 * Preserve pc across advance, so that we can delay
4061 * the writeback to rd until after src is consumed.
4062 */
4063 target_ulong cur_pc = dc->pc;
4064
4065 gen_check_align(dc, src, 3);
4066
4067 gen_mov_pc_npc(dc);
4068 tcg_gen_mov_tl(cpu_npc, src);
4069 gen_address_mask(dc, cpu_npc);
4070 gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
4071
4072 dc->npc = DYNAMIC_PC_LOOKUP;
4073 return true;
4074 }
4075
4076 TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
4077
4078 static bool do_rett(DisasContext *dc, int rd, TCGv src)
4079 {
4080 if (!supervisor(dc)) {
4081 return raise_priv(dc);
4082 }
4083
4084 gen_check_align(dc, src, 3);
4085
4086 gen_mov_pc_npc(dc);
4087 tcg_gen_mov_tl(cpu_npc, src);
4088 gen_helper_rett(tcg_env);
4089
4090 dc->npc = DYNAMIC_PC;
4091 return true;
4092 }
4093
4094 TRANS(RETT, 32, do_add_special, a, do_rett)
4095
4096 static bool do_return(DisasContext *dc, int rd, TCGv src)
4097 {
4098 gen_check_align(dc, src, 3);
4099 gen_helper_restore(tcg_env);
4100
4101 gen_mov_pc_npc(dc);
4102 tcg_gen_mov_tl(cpu_npc, src);
4103 gen_address_mask(dc, cpu_npc);
4104
4105 dc->npc = DYNAMIC_PC_LOOKUP;
4106 return true;
4107 }
4108
4109 TRANS(RETURN, 64, do_add_special, a, do_return)
4110
4111 static bool do_save(DisasContext *dc, int rd, TCGv src)
4112 {
4113 gen_helper_save(tcg_env);
4114 gen_store_gpr(dc, rd, src);
4115 return advance_pc(dc);
4116 }
4117
4118 TRANS(SAVE, ALL, do_add_special, a, do_save)
4119
4120 static bool do_restore(DisasContext *dc, int rd, TCGv src)
4121 {
4122 gen_helper_restore(tcg_env);
4123 gen_store_gpr(dc, rd, src);
4124 return advance_pc(dc);
4125 }
4126
4127 TRANS(RESTORE, ALL, do_add_special, a, do_restore)
4128
4129 static bool do_done_retry(DisasContext *dc, bool done)
4130 {
4131 if (!supervisor(dc)) {
4132 return raise_priv(dc);
4133 }
4134 dc->npc = DYNAMIC_PC;
4135 dc->pc = DYNAMIC_PC;
4136 translator_io_start(&dc->base);
4137 if (done) {
4138 gen_helper_done(tcg_env);
4139 } else {
4140 gen_helper_retry(tcg_env);
4141 }
4142 return true;
4143 }
4144
4145 TRANS(DONE, 64, do_done_retry, true)
4146 TRANS(RETRY, 64, do_done_retry, false)
4147
4148 /*
4149 * Major opcode 11 -- load and store instructions
4150 */
4151
4152 static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
4153 {
4154 TCGv addr, tmp = NULL;
4155
4156 /* For simplicity, we under-decoded the rs2 form. */
4157 if (!imm && rs2_or_imm & ~0x1f) {
4158 return NULL;
4159 }
4160
4161 addr = gen_load_gpr(dc, rs1);
4162 if (rs2_or_imm) {
4163 tmp = tcg_temp_new();
4164 if (imm) {
4165 tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
4166 } else {
4167 tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
4168 }
4169 addr = tmp;
4170 }
4171 if (AM_CHECK(dc)) {
4172 if (!tmp) {
4173 tmp = tcg_temp_new();
4174 }
4175 tcg_gen_ext32u_tl(tmp, addr);
4176 addr = tmp;
4177 }
4178 return addr;
4179 }
4180
4181 static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4182 {
4183 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4184 DisasASI da;
4185
4186 if (addr == NULL) {
4187 return false;
4188 }
4189 da = resolve_asi(dc, a->asi, mop);
4190
4191 reg = gen_dest_gpr(dc, a->rd);
4192 gen_ld_asi(dc, &da, reg, addr);
4193 gen_store_gpr(dc, a->rd, reg);
4194 return advance_pc(dc);
4195 }
4196
4197 TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
4198 TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
4199 TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
4200 TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
4201 TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
4202 TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
4203 TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
4204
4205 static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4206 {
4207 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4208 DisasASI da;
4209
4210 if (addr == NULL) {
4211 return false;
4212 }
4213 da = resolve_asi(dc, a->asi, mop);
4214
4215 reg = gen_load_gpr(dc, a->rd);
4216 gen_st_asi(dc, &da, reg, addr);
4217 return advance_pc(dc);
4218 }
4219
4220 TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
4221 TRANS(STB, ALL, do_st_gpr, a, MO_UB)
4222 TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
4223 TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
4224
4225 static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
4226 {
4227 TCGv addr;
4228 DisasASI da;
4229
4230 if (a->rd & 1) {
4231 return false;
4232 }
4233 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4234 if (addr == NULL) {
4235 return false;
4236 }
4237 da = resolve_asi(dc, a->asi, MO_TEUQ);
4238 gen_ldda_asi(dc, &da, addr, a->rd);
4239 return advance_pc(dc);
4240 }
4241
4242 static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
4243 {
4244 TCGv addr;
4245 DisasASI da;
4246
4247 if (a->rd & 1) {
4248 return false;
4249 }
4250 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4251 if (addr == NULL) {
4252 return false;
4253 }
4254 da = resolve_asi(dc, a->asi, MO_TEUQ);
4255 gen_stda_asi(dc, &da, addr, a->rd);
4256 return advance_pc(dc);
4257 }
4258
4259 static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
4260 {
4261 TCGv addr, reg;
4262 DisasASI da;
4263
4264 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4265 if (addr == NULL) {
4266 return false;
4267 }
4268 da = resolve_asi(dc, a->asi, MO_UB);
4269
4270 reg = gen_dest_gpr(dc, a->rd);
4271 gen_ldstub_asi(dc, &da, reg, addr);
4272 gen_store_gpr(dc, a->rd, reg);
4273 return advance_pc(dc);
4274 }
4275
4276 static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
4277 {
4278 TCGv addr, dst, src;
4279 DisasASI da;
4280
4281 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4282 if (addr == NULL) {
4283 return false;
4284 }
4285 da = resolve_asi(dc, a->asi, MO_TEUL);
4286
4287 dst = gen_dest_gpr(dc, a->rd);
4288 src = gen_load_gpr(dc, a->rd);
4289 gen_swap_asi(dc, &da, dst, src, addr);
4290 gen_store_gpr(dc, a->rd, dst);
4291 return advance_pc(dc);
4292 }
4293
4294 static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4295 {
4296 TCGv addr, o, n, c;
4297 DisasASI da;
4298
4299 addr = gen_ldst_addr(dc, a->rs1, true, 0);
4300 if (addr == NULL) {
4301 return false;
4302 }
4303 da = resolve_asi(dc, a->asi, mop);
4304
4305 o = gen_dest_gpr(dc, a->rd);
4306 n = gen_load_gpr(dc, a->rd);
4307 c = gen_load_gpr(dc, a->rs2_or_imm);
4308 gen_cas_asi(dc, &da, o, n, c, addr);
4309 gen_store_gpr(dc, a->rd, o);
4310 return advance_pc(dc);
4311 }
4312
4313 TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4314 TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4315
4316 static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
4317 {
4318 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4319 DisasASI da;
4320
4321 if (addr == NULL) {
4322 return false;
4323 }
4324 if (gen_trap_ifnofpu(dc)) {
4325 return true;
4326 }
4327 if (sz == MO_128 && gen_trap_float128(dc)) {
4328 return true;
4329 }
4330 da = resolve_asi(dc, a->asi, MO_TE | sz);
4331 gen_ldf_asi(dc, &da, sz, addr, a->rd);
4332 gen_update_fprs_dirty(dc, a->rd);
4333 return advance_pc(dc);
4334 }
4335
4336 TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
4337 TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
4338 TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
4339
4340 TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4341 TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4342 TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4343
4344 static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
4345 {
4346 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4347 DisasASI da;
4348
4349 if (addr == NULL) {
4350 return false;
4351 }
4352 if (gen_trap_ifnofpu(dc)) {
4353 return true;
4354 }
4355 if (sz == MO_128 && gen_trap_float128(dc)) {
4356 return true;
4357 }
4358 da = resolve_asi(dc, a->asi, MO_TE | sz);
4359 gen_stf_asi(dc, &da, sz, addr, a->rd);
4360 return advance_pc(dc);
4361 }
4362
4363 TRANS(STF, ALL, do_st_fpr, a, MO_32)
4364 TRANS(STDF, ALL, do_st_fpr, a, MO_64)
4365 TRANS(STQF, ALL, do_st_fpr, a, MO_128)
4366
4367 TRANS(STFA, 64, do_st_fpr, a, MO_32)
4368 TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4369 TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4370
4371 static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
4372 {
4373 if (!avail_32(dc)) {
4374 return false;
4375 }
4376 if (!supervisor(dc)) {
4377 return raise_priv(dc);
4378 }
4379 if (gen_trap_ifnofpu(dc)) {
4380 return true;
4381 }
4382 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
4383 return true;
4384 }
4385
4386 static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop,
4387 target_ulong new_mask, target_ulong old_mask)
4388 {
4389 TCGv tmp, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4390 if (addr == NULL) {
4391 return false;
4392 }
4393 if (gen_trap_ifnofpu(dc)) {
4394 return true;
4395 }
4396 tmp = tcg_temp_new();
4397 tcg_gen_qemu_ld_tl(tmp, addr, dc->mem_idx, mop | MO_ALIGN);
4398 tcg_gen_andi_tl(tmp, tmp, new_mask);
4399 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, old_mask);
4400 tcg_gen_or_tl(cpu_fsr, cpu_fsr, tmp);
4401 gen_helper_set_fsr(tcg_env, cpu_fsr);
4402 return advance_pc(dc);
4403 }
4404
4405 TRANS(LDFSR, ALL, do_ldfsr, a, MO_TEUL, FSR_LDFSR_MASK, FSR_LDFSR_OLDMASK)
4406 TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK)
4407
4408 static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
4409 {
4410 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4411 if (addr == NULL) {
4412 return false;
4413 }
4414 if (gen_trap_ifnofpu(dc)) {
4415 return true;
4416 }
4417 tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN);
4418 return advance_pc(dc);
4419 }
4420
4421 TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
4422 TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
4423
4424 static bool do_fc(DisasContext *dc, int rd, bool c)
4425 {
4426 uint64_t mask;
4427
4428 if (gen_trap_ifnofpu(dc)) {
4429 return true;
4430 }
4431
4432 if (rd & 1) {
4433 mask = MAKE_64BIT_MASK(0, 32);
4434 } else {
4435 mask = MAKE_64BIT_MASK(32, 32);
4436 }
4437 if (c) {
4438 tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask);
4439 } else {
4440 tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask);
4441 }
4442 gen_update_fprs_dirty(dc, rd);
4443 return advance_pc(dc);
4444 }
4445
4446 TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
4447 TRANS(FONEs, VIS1, do_fc, a->rd, 1)
4448
4449 static bool do_dc(DisasContext *dc, int rd, int64_t c)
4450 {
4451 if (gen_trap_ifnofpu(dc)) {
4452 return true;
4453 }
4454
4455 tcg_gen_movi_i64(cpu_fpr[rd / 2], c);
4456 gen_update_fprs_dirty(dc, rd);
4457 return advance_pc(dc);
4458 }
4459
4460 TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
4461 TRANS(FONEd, VIS1, do_dc, a->rd, -1)
4462
4463 static bool do_ff(DisasContext *dc, arg_r_r *a,
4464 void (*func)(TCGv_i32, TCGv_i32))
4465 {
4466 TCGv_i32 tmp;
4467
4468 if (gen_trap_ifnofpu(dc)) {
4469 return true;
4470 }
4471
4472 tmp = gen_load_fpr_F(dc, a->rs);
4473 func(tmp, tmp);
4474 gen_store_fpr_F(dc, a->rd, tmp);
4475 return advance_pc(dc);
4476 }
4477
4478 TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4479 TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4480 TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4481 TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4482 TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4483
4484 static bool do_fd(DisasContext *dc, arg_r_r *a,
4485 void (*func)(TCGv_i32, TCGv_i64))
4486 {
4487 TCGv_i32 dst;
4488 TCGv_i64 src;
4489
4490 if (gen_trap_ifnofpu(dc)) {
4491 return true;
4492 }
4493
4494 dst = gen_dest_fpr_F(dc);
4495 src = gen_load_fpr_D(dc, a->rs);
4496 func(dst, src);
4497 gen_store_fpr_F(dc, a->rd, dst);
4498 return advance_pc(dc);
4499 }
4500
4501 TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
4502 TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
4503
4504 static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4505 void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4506 {
4507 TCGv_i32 tmp;
4508
4509 if (gen_trap_ifnofpu(dc)) {
4510 return true;
4511 }
4512
4513 gen_op_clear_ieee_excp_and_FTT();
4514 tmp = gen_load_fpr_F(dc, a->rs);
4515 func(tmp, tcg_env, tmp);
4516 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4517 gen_store_fpr_F(dc, a->rd, tmp);
4518 return advance_pc(dc);
4519 }
4520
4521 TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4522 TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4523 TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4524
4525 static bool do_env_fd(DisasContext *dc, arg_r_r *a,
4526 void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
4527 {
4528 TCGv_i32 dst;
4529 TCGv_i64 src;
4530
4531 if (gen_trap_ifnofpu(dc)) {
4532 return true;
4533 }
4534
4535 gen_op_clear_ieee_excp_and_FTT();
4536 dst = gen_dest_fpr_F(dc);
4537 src = gen_load_fpr_D(dc, a->rs);
4538 func(dst, tcg_env, src);
4539 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4540 gen_store_fpr_F(dc, a->rd, dst);
4541 return advance_pc(dc);
4542 }
4543
4544 TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
4545 TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
4546 TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
4547
4548 static bool do_dd(DisasContext *dc, arg_r_r *a,
4549 void (*func)(TCGv_i64, TCGv_i64))
4550 {
4551 TCGv_i64 dst, src;
4552
4553 if (gen_trap_ifnofpu(dc)) {
4554 return true;
4555 }
4556
4557 dst = gen_dest_fpr_D(dc, a->rd);
4558 src = gen_load_fpr_D(dc, a->rs);
4559 func(dst, src);
4560 gen_store_fpr_D(dc, a->rd, dst);
4561 return advance_pc(dc);
4562 }
4563
4564 TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4565 TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4566 TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4567 TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4568 TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4569
4570 static bool do_env_dd(DisasContext *dc, arg_r_r *a,
4571 void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
4572 {
4573 TCGv_i64 dst, src;
4574
4575 if (gen_trap_ifnofpu(dc)) {
4576 return true;
4577 }
4578
4579 gen_op_clear_ieee_excp_and_FTT();
4580 dst = gen_dest_fpr_D(dc, a->rd);
4581 src = gen_load_fpr_D(dc, a->rs);
4582 func(dst, tcg_env, src);
4583 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4584 gen_store_fpr_D(dc, a->rd, dst);
4585 return advance_pc(dc);
4586 }
4587
4588 TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
4589 TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
4590 TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
4591
4592 static bool do_env_df(DisasContext *dc, arg_r_r *a,
4593 void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4594 {
4595 TCGv_i64 dst;
4596 TCGv_i32 src;
4597
4598 if (gen_trap_ifnofpu(dc)) {
4599 return true;
4600 }
4601
4602 gen_op_clear_ieee_excp_and_FTT();
4603 dst = gen_dest_fpr_D(dc, a->rd);
4604 src = gen_load_fpr_F(dc, a->rs);
4605 func(dst, tcg_env, src);
4606 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4607 gen_store_fpr_D(dc, a->rd, dst);
4608 return advance_pc(dc);
4609 }
4610
4611 TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4612 TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4613 TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4614
4615 static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a)
4616 {
4617 int rd, rs;
4618
4619 if (!avail_64(dc)) {
4620 return false;
4621 }
4622 if (gen_trap_ifnofpu(dc)) {
4623 return true;
4624 }
4625 if (gen_trap_float128(dc)) {
4626 return true;
4627 }
4628
4629 gen_op_clear_ieee_excp_and_FTT();
4630 rd = QFPREG(a->rd);
4631 rs = QFPREG(a->rs);
4632 tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
4633 tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
4634 gen_update_fprs_dirty(dc, rd);
4635 return advance_pc(dc);
4636 }
4637
4638 static bool do_qq(DisasContext *dc, arg_r_r *a,
4639 void (*func)(TCGv_env))
4640 {
4641 if (gen_trap_ifnofpu(dc)) {
4642 return true;
4643 }
4644 if (gen_trap_float128(dc)) {
4645 return true;
4646 }
4647
4648 gen_op_clear_ieee_excp_and_FTT();
4649 gen_op_load_fpr_QT1(QFPREG(a->rs));
4650 func(tcg_env);
4651 gen_op_store_QT0_fpr(QFPREG(a->rd));
4652 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4653 return advance_pc(dc);
4654 }
4655
4656 TRANS(FNEGq, 64, do_qq, a, gen_helper_fnegq)
4657 TRANS(FABSq, 64, do_qq, a, gen_helper_fabsq)
4658
4659 static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4660 void (*func)(TCGv_env))
4661 {
4662 if (gen_trap_ifnofpu(dc)) {
4663 return true;
4664 }
4665 if (gen_trap_float128(dc)) {
4666 return true;
4667 }
4668
4669 gen_op_clear_ieee_excp_and_FTT();
4670 gen_op_load_fpr_QT1(QFPREG(a->rs));
4671 func(tcg_env);
4672 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4673 gen_op_store_QT0_fpr(QFPREG(a->rd));
4674 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4675 return advance_pc(dc);
4676 }
4677
4678 TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4679
4680 static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4681 void (*func)(TCGv_i32, TCGv_env))
4682 {
4683 TCGv_i32 dst;
4684
4685 if (gen_trap_ifnofpu(dc)) {
4686 return true;
4687 }
4688 if (gen_trap_float128(dc)) {
4689 return true;
4690 }
4691
4692 gen_op_clear_ieee_excp_and_FTT();
4693 gen_op_load_fpr_QT1(QFPREG(a->rs));
4694 dst = gen_dest_fpr_F(dc);
4695 func(dst, tcg_env);
4696 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4697 gen_store_fpr_F(dc, a->rd, dst);
4698 return advance_pc(dc);
4699 }
4700
4701 TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4702 TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4703
4704 static bool do_env_dq(DisasContext *dc, arg_r_r *a,
4705 void (*func)(TCGv_i64, TCGv_env))
4706 {
4707 TCGv_i64 dst;
4708
4709 if (gen_trap_ifnofpu(dc)) {
4710 return true;
4711 }
4712 if (gen_trap_float128(dc)) {
4713 return true;
4714 }
4715
4716 gen_op_clear_ieee_excp_and_FTT();
4717 gen_op_load_fpr_QT1(QFPREG(a->rs));
4718 dst = gen_dest_fpr_D(dc, a->rd);
4719 func(dst, tcg_env);
4720 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4721 gen_store_fpr_D(dc, a->rd, dst);
4722 return advance_pc(dc);
4723 }
4724
4725 TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
4726 TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
4727
4728 static bool do_env_qf(DisasContext *dc, arg_r_r *a,
4729 void (*func)(TCGv_env, TCGv_i32))
4730 {
4731 TCGv_i32 src;
4732
4733 if (gen_trap_ifnofpu(dc)) {
4734 return true;
4735 }
4736 if (gen_trap_float128(dc)) {
4737 return true;
4738 }
4739
4740 gen_op_clear_ieee_excp_and_FTT();
4741 src = gen_load_fpr_F(dc, a->rs);
4742 func(tcg_env, src);
4743 gen_op_store_QT0_fpr(QFPREG(a->rd));
4744 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4745 return advance_pc(dc);
4746 }
4747
4748 TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
4749 TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
4750
4751 static bool do_env_qd(DisasContext *dc, arg_r_r *a,
4752 void (*func)(TCGv_env, TCGv_i64))
4753 {
4754 TCGv_i64 src;
4755
4756 if (gen_trap_ifnofpu(dc)) {
4757 return true;
4758 }
4759 if (gen_trap_float128(dc)) {
4760 return true;
4761 }
4762
4763 gen_op_clear_ieee_excp_and_FTT();
4764 src = gen_load_fpr_D(dc, a->rs);
4765 func(tcg_env, src);
4766 gen_op_store_QT0_fpr(QFPREG(a->rd));
4767 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4768 return advance_pc(dc);
4769 }
4770
4771 TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
4772 TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
4773
4774 static bool do_fff(DisasContext *dc, arg_r_r_r *a,
4775 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
4776 {
4777 TCGv_i32 src1, src2;
4778
4779 if (gen_trap_ifnofpu(dc)) {
4780 return true;
4781 }
4782
4783 src1 = gen_load_fpr_F(dc, a->rs1);
4784 src2 = gen_load_fpr_F(dc, a->rs2);
4785 func(src1, src1, src2);
4786 gen_store_fpr_F(dc, a->rd, src1);
4787 return advance_pc(dc);
4788 }
4789
4790 TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
4791 TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
4792 TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
4793 TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
4794 TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
4795 TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
4796 TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
4797 TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
4798 TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
4799 TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
4800 TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
4801 TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
4802
4803 static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
4804 void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
4805 {
4806 TCGv_i32 src1, src2;
4807
4808 if (gen_trap_ifnofpu(dc)) {
4809 return true;
4810 }
4811
4812 gen_op_clear_ieee_excp_and_FTT();
4813 src1 = gen_load_fpr_F(dc, a->rs1);
4814 src2 = gen_load_fpr_F(dc, a->rs2);
4815 func(src1, tcg_env, src1, src2);
4816 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4817 gen_store_fpr_F(dc, a->rd, src1);
4818 return advance_pc(dc);
4819 }
4820
4821 TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
4822 TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
4823 TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
4824 TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
4825
4826 static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
4827 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
4828 {
4829 TCGv_i64 dst, src1, src2;
4830
4831 if (gen_trap_ifnofpu(dc)) {
4832 return true;
4833 }
4834
4835 dst = gen_dest_fpr_D(dc, a->rd);
4836 src1 = gen_load_fpr_D(dc, a->rs1);
4837 src2 = gen_load_fpr_D(dc, a->rs2);
4838 func(dst, src1, src2);
4839 gen_store_fpr_D(dc, a->rd, dst);
4840 return advance_pc(dc);
4841 }
4842
4843 TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16)
4844 TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au)
4845 TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al)
4846 TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
4847 TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
4848 TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16)
4849 TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16)
4850 TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge)
4851 TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand)
4852
4853 TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64)
4854 TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64)
4855 TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64)
4856 TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64)
4857 TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
4858 TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
4859 TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
4860 TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
4861 TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
4862 TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
4863 TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
4864 TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
4865
4866 TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
4867 TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata)
4868 TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
4869
4870 static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
4871 void (*func)(TCGv, TCGv_i64, TCGv_i64))
4872 {
4873 TCGv_i64 src1, src2;
4874 TCGv dst;
4875
4876 if (gen_trap_ifnofpu(dc)) {
4877 return true;
4878 }
4879
4880 dst = gen_dest_gpr(dc, a->rd);
4881 src1 = gen_load_fpr_D(dc, a->rs1);
4882 src2 = gen_load_fpr_D(dc, a->rs2);
4883 func(dst, src1, src2);
4884 gen_store_gpr(dc, a->rd, dst);
4885 return advance_pc(dc);
4886 }
4887
4888 TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
4889 TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
4890 TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
4891 TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
4892
4893 TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
4894 TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
4895 TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
4896 TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
4897
4898 static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
4899 void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
4900 {
4901 TCGv_i64 dst, src1, src2;
4902
4903 if (gen_trap_ifnofpu(dc)) {
4904 return true;
4905 }
4906
4907 gen_op_clear_ieee_excp_and_FTT();
4908 dst = gen_dest_fpr_D(dc, a->rd);
4909 src1 = gen_load_fpr_D(dc, a->rs1);
4910 src2 = gen_load_fpr_D(dc, a->rs2);
4911 func(dst, tcg_env, src1, src2);
4912 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4913 gen_store_fpr_D(dc, a->rd, dst);
4914 return advance_pc(dc);
4915 }
4916
4917 TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
4918 TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
4919 TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
4920 TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
4921
4922 static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
4923 {
4924 TCGv_i64 dst;
4925 TCGv_i32 src1, src2;
4926
4927 if (gen_trap_ifnofpu(dc)) {
4928 return true;
4929 }
4930 if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
4931 return raise_unimpfpop(dc);
4932 }
4933
4934 gen_op_clear_ieee_excp_and_FTT();
4935 dst = gen_dest_fpr_D(dc, a->rd);
4936 src1 = gen_load_fpr_F(dc, a->rs1);
4937 src2 = gen_load_fpr_F(dc, a->rs2);
4938 gen_helper_fsmuld(dst, tcg_env, src1, src2);
4939 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4940 gen_store_fpr_D(dc, a->rd, dst);
4941 return advance_pc(dc);
4942 }
4943
4944 static bool do_dddd(DisasContext *dc, arg_r_r_r *a,
4945 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
4946 {
4947 TCGv_i64 dst, src0, src1, src2;
4948
4949 if (gen_trap_ifnofpu(dc)) {
4950 return true;
4951 }
4952
4953 dst = gen_dest_fpr_D(dc, a->rd);
4954 src0 = gen_load_fpr_D(dc, a->rd);
4955 src1 = gen_load_fpr_D(dc, a->rs1);
4956 src2 = gen_load_fpr_D(dc, a->rs2);
4957 func(dst, src0, src1, src2);
4958 gen_store_fpr_D(dc, a->rd, dst);
4959 return advance_pc(dc);
4960 }
4961
4962 TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
4963
4964 static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
4965 void (*func)(TCGv_env))
4966 {
4967 if (gen_trap_ifnofpu(dc)) {
4968 return true;
4969 }
4970 if (gen_trap_float128(dc)) {
4971 return true;
4972 }
4973
4974 gen_op_clear_ieee_excp_and_FTT();
4975 gen_op_load_fpr_QT0(QFPREG(a->rs1));
4976 gen_op_load_fpr_QT1(QFPREG(a->rs2));
4977 func(tcg_env);
4978 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4979 gen_op_store_QT0_fpr(QFPREG(a->rd));
4980 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4981 return advance_pc(dc);
4982 }
4983
4984 TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
4985 TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
4986 TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
4987 TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
4988
4989 static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
4990 {
4991 TCGv_i64 src1, src2;
4992
4993 if (gen_trap_ifnofpu(dc)) {
4994 return true;
4995 }
4996 if (gen_trap_float128(dc)) {
4997 return true;
4998 }
4999
5000 gen_op_clear_ieee_excp_and_FTT();
5001 src1 = gen_load_fpr_D(dc, a->rs1);
5002 src2 = gen_load_fpr_D(dc, a->rs2);
5003 gen_helper_fdmulq(tcg_env, src1, src2);
5004 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
5005 gen_op_store_QT0_fpr(QFPREG(a->rd));
5006 gen_update_fprs_dirty(dc, QFPREG(a->rd));
5007 return advance_pc(dc);
5008 }
5009
5010 static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
5011 void (*func)(DisasContext *, DisasCompare *, int, int))
5012 {
5013 DisasCompare cmp;
5014
5015 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
5016 return false;
5017 }
5018 if (gen_trap_ifnofpu(dc)) {
5019 return true;
5020 }
5021 if (is_128 && gen_trap_float128(dc)) {
5022 return true;
5023 }
5024
5025 gen_op_clear_ieee_excp_and_FTT();
5026 func(dc, &cmp, a->rd, a->rs2);
5027 return advance_pc(dc);
5028 }
5029
5030 TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
5031 TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
5032 TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
5033
5034 static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
5035 void (*func)(DisasContext *, DisasCompare *, int, int))
5036 {
5037 DisasCompare cmp;
5038
5039 if (gen_trap_ifnofpu(dc)) {
5040 return true;
5041 }
5042 if (is_128 && gen_trap_float128(dc)) {
5043 return true;
5044 }
5045
5046 gen_op_clear_ieee_excp_and_FTT();
5047 gen_compare(&cmp, a->cc, a->cond, dc);
5048 func(dc, &cmp, a->rd, a->rs2);
5049 return advance_pc(dc);
5050 }
5051
5052 TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
5053 TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
5054 TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
5055
5056 static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
5057 void (*func)(DisasContext *, DisasCompare *, int, int))
5058 {
5059 DisasCompare cmp;
5060
5061 if (gen_trap_ifnofpu(dc)) {
5062 return true;
5063 }
5064 if (is_128 && gen_trap_float128(dc)) {
5065 return true;
5066 }
5067
5068 gen_op_clear_ieee_excp_and_FTT();
5069 gen_fcompare(&cmp, a->cc, a->cond);
5070 func(dc, &cmp, a->rd, a->rs2);
5071 return advance_pc(dc);
5072 }
5073
5074 TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
5075 TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
5076 TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
5077
5078 static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
5079 {
5080 TCGv_i32 src1, src2;
5081
5082 if (avail_32(dc) && a->cc != 0) {
5083 return false;
5084 }
5085 if (gen_trap_ifnofpu(dc)) {
5086 return true;
5087 }
5088
5089 gen_op_clear_ieee_excp_and_FTT();
5090 src1 = gen_load_fpr_F(dc, a->rs1);
5091 src2 = gen_load_fpr_F(dc, a->rs2);
5092 if (e) {
5093 gen_op_fcmpes(a->cc, src1, src2);
5094 } else {
5095 gen_op_fcmps(a->cc, src1, src2);
5096 }
5097 return advance_pc(dc);
5098 }
5099
5100 TRANS(FCMPs, ALL, do_fcmps, a, false)
5101 TRANS(FCMPEs, ALL, do_fcmps, a, true)
5102
5103 static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
5104 {
5105 TCGv_i64 src1, src2;
5106
5107 if (avail_32(dc) && a->cc != 0) {
5108 return false;
5109 }
5110 if (gen_trap_ifnofpu(dc)) {
5111 return true;
5112 }
5113
5114 gen_op_clear_ieee_excp_and_FTT();
5115 src1 = gen_load_fpr_D(dc, a->rs1);
5116 src2 = gen_load_fpr_D(dc, a->rs2);
5117 if (e) {
5118 gen_op_fcmped(a->cc, src1, src2);
5119 } else {
5120 gen_op_fcmpd(a->cc, src1, src2);
5121 }
5122 return advance_pc(dc);
5123 }
5124
5125 TRANS(FCMPd, ALL, do_fcmpd, a, false)
5126 TRANS(FCMPEd, ALL, do_fcmpd, a, true)
5127
5128 static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
5129 {
5130 if (avail_32(dc) && a->cc != 0) {
5131 return false;
5132 }
5133 if (gen_trap_ifnofpu(dc)) {
5134 return true;
5135 }
5136 if (gen_trap_float128(dc)) {
5137 return true;
5138 }
5139
5140 gen_op_clear_ieee_excp_and_FTT();
5141 gen_op_load_fpr_QT0(QFPREG(a->rs1));
5142 gen_op_load_fpr_QT1(QFPREG(a->rs2));
5143 if (e) {
5144 gen_op_fcmpeq(a->cc);
5145 } else {
5146 gen_op_fcmpq(a->cc);
5147 }
5148 return advance_pc(dc);
5149 }
5150
5151 TRANS(FCMPq, ALL, do_fcmpq, a, false)
5152 TRANS(FCMPEq, ALL, do_fcmpq, a, true)
5153
5154 static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
5155 {
5156 DisasContext *dc = container_of(dcbase, DisasContext, base);
5157 CPUSPARCState *env = cpu_env(cs);
5158 int bound;
5159
5160 dc->pc = dc->base.pc_first;
5161 dc->npc = (target_ulong)dc->base.tb->cs_base;
5162 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
5163 dc->def = &env->def;
5164 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
5165 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
5166 #ifndef CONFIG_USER_ONLY
5167 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
5168 #endif
5169 #ifdef TARGET_SPARC64
5170 dc->fprs_dirty = 0;
5171 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
5172 #ifndef CONFIG_USER_ONLY
5173 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
5174 #endif
5175 #endif
5176 /*
5177 * if we reach a page boundary, we stop generation so that the
5178 * PC of a TT_TFAULT exception is always in the right page
5179 */
5180 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
5181 dc->base.max_insns = MIN(dc->base.max_insns, bound);
5182 }
5183
5184 static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
5185 {
5186 }
5187
5188 static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
5189 {
5190 DisasContext *dc = container_of(dcbase, DisasContext, base);
5191 target_ulong npc = dc->npc;
5192
5193 if (npc & 3) {
5194 switch (npc) {
5195 case JUMP_PC:
5196 assert(dc->jump_pc[1] == dc->pc + 4);
5197 npc = dc->jump_pc[0] | JUMP_PC;
5198 break;
5199 case DYNAMIC_PC:
5200 case DYNAMIC_PC_LOOKUP:
5201 npc = DYNAMIC_PC;
5202 break;
5203 default:
5204 g_assert_not_reached();
5205 }
5206 }
5207 tcg_gen_insn_start(dc->pc, npc);
5208 }
5209
5210 static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
5211 {
5212 DisasContext *dc = container_of(dcbase, DisasContext, base);
5213 CPUSPARCState *env = cpu_env(cs);
5214 unsigned int insn;
5215
5216 insn = translator_ldl(env, &dc->base, dc->pc);
5217 dc->base.pc_next += 4;
5218
5219 if (!decode(dc, insn)) {
5220 gen_exception(dc, TT_ILL_INSN);
5221 }
5222
5223 if (dc->base.is_jmp == DISAS_NORETURN) {
5224 return;
5225 }
5226 if (dc->pc != dc->base.pc_next) {
5227 dc->base.is_jmp = DISAS_TOO_MANY;
5228 }
5229 }
5230
5231 static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
5232 {
5233 DisasContext *dc = container_of(dcbase, DisasContext, base);
5234 DisasDelayException *e, *e_next;
5235 bool may_lookup;
5236
5237 finishing_insn(dc);
5238
5239 switch (dc->base.is_jmp) {
5240 case DISAS_NEXT:
5241 case DISAS_TOO_MANY:
5242 if (((dc->pc | dc->npc) & 3) == 0) {
5243 /* static PC and NPC: we can use direct chaining */
5244 gen_goto_tb(dc, 0, dc->pc, dc->npc);
5245 break;
5246 }
5247
5248 may_lookup = true;
5249 if (dc->pc & 3) {
5250 switch (dc->pc) {
5251 case DYNAMIC_PC_LOOKUP:
5252 break;
5253 case DYNAMIC_PC:
5254 may_lookup = false;
5255 break;
5256 default:
5257 g_assert_not_reached();
5258 }
5259 } else {
5260 tcg_gen_movi_tl(cpu_pc, dc->pc);
5261 }
5262
5263 if (dc->npc & 3) {
5264 switch (dc->npc) {
5265 case JUMP_PC:
5266 gen_generic_branch(dc);
5267 break;
5268 case DYNAMIC_PC:
5269 may_lookup = false;
5270 break;
5271 case DYNAMIC_PC_LOOKUP:
5272 break;
5273 default:
5274 g_assert_not_reached();
5275 }
5276 } else {
5277 tcg_gen_movi_tl(cpu_npc, dc->npc);
5278 }
5279 if (may_lookup) {
5280 tcg_gen_lookup_and_goto_ptr();
5281 } else {
5282 tcg_gen_exit_tb(NULL, 0);
5283 }
5284 break;
5285
5286 case DISAS_NORETURN:
5287 break;
5288
5289 case DISAS_EXIT:
5290 /* Exit TB */
5291 save_state(dc);
5292 tcg_gen_exit_tb(NULL, 0);
5293 break;
5294
5295 default:
5296 g_assert_not_reached();
5297 }
5298
5299 for (e = dc->delay_excp_list; e ; e = e_next) {
5300 gen_set_label(e->lab);
5301
5302 tcg_gen_movi_tl(cpu_pc, e->pc);
5303 if (e->npc % 4 == 0) {
5304 tcg_gen_movi_tl(cpu_npc, e->npc);
5305 }
5306 gen_helper_raise_exception(tcg_env, e->excp);
5307
5308 e_next = e->next;
5309 g_free(e);
5310 }
5311 }
5312
5313 static void sparc_tr_disas_log(const DisasContextBase *dcbase,
5314 CPUState *cpu, FILE *logfile)
5315 {
5316 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
5317 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
5318 }
5319
5320 static const TranslatorOps sparc_tr_ops = {
5321 .init_disas_context = sparc_tr_init_disas_context,
5322 .tb_start = sparc_tr_tb_start,
5323 .insn_start = sparc_tr_insn_start,
5324 .translate_insn = sparc_tr_translate_insn,
5325 .tb_stop = sparc_tr_tb_stop,
5326 .disas_log = sparc_tr_disas_log,
5327 };
5328
5329 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
5330 target_ulong pc, void *host_pc)
5331 {
5332 DisasContext dc = {};
5333
5334 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
5335 }
5336
5337 void sparc_tcg_init(void)
5338 {
5339 static const char gregnames[32][4] = {
5340 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5341 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5342 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5343 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5344 };
5345 static const char fregnames[32][4] = {
5346 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5347 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5348 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5349 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5350 };
5351
5352 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5353 #ifdef TARGET_SPARC64
5354 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
5355 { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
5356 { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
5357 #endif
5358 { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
5359 { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
5360 { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
5361 { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
5362 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5363 { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
5364 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5365 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5366 { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5367 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5368 };
5369
5370 unsigned int i;
5371
5372 cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
5373 offsetof(CPUSPARCState, regwptr),
5374 "regwptr");
5375
5376 for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5377 *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
5378 }
5379
5380 cpu_regs[0] = NULL;
5381 for (i = 1; i < 8; ++i) {
5382 cpu_regs[i] = tcg_global_mem_new(tcg_env,
5383 offsetof(CPUSPARCState, gregs[i]),
5384 gregnames[i]);
5385 }
5386
5387 for (i = 8; i < 32; ++i) {
5388 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5389 (i - 8) * sizeof(target_ulong),
5390 gregnames[i]);
5391 }
5392
5393 for (i = 0; i < TARGET_DPREGS; i++) {
5394 cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env,
5395 offsetof(CPUSPARCState, fpr[i]),
5396 fregnames[i]);
5397 }
5398
5399 #ifdef TARGET_SPARC64
5400 cpu_fprs = tcg_global_mem_new_i32(tcg_env,
5401 offsetof(CPUSPARCState, fprs), "fprs");
5402 #endif
5403 }
5404
5405 void sparc_restore_state_to_opc(CPUState *cs,
5406 const TranslationBlock *tb,
5407 const uint64_t *data)
5408 {
5409 SPARCCPU *cpu = SPARC_CPU(cs);
5410 CPUSPARCState *env = &cpu->env;
5411 target_ulong pc = data[0];
5412 target_ulong npc = data[1];
5413
5414 env->pc = pc;
5415 if (npc == DYNAMIC_PC) {
5416 /* dynamic NPC: already stored */
5417 } else if (npc & JUMP_PC) {
5418 /* jump PC: use 'cond' and the jump targets of the translation */
5419 if (env->cond) {
5420 env->npc = npc & ~3;
5421 } else {
5422 env->npc = pc + 4;
5423 }
5424 } else {
5425 env->npc = npc;
5426 }
5427 }