]> git.proxmox.com Git - mirror_qemu.git/blame - target-sparc/translate.c
More helper types, rearrange generic definitions
[mirror_qemu.git] / target-sparc / translate.c
CommitLineData
7a3f1944
FB
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
3475187d 5 Copyright (C) 2003-2005 Fabrice Bellard
7a3f1944
FB
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/*
7a3f1944
FB
23 TODO-list:
24
3475187d 25 Rest of V9 instructions, VIS instructions
bd497938 26 NPC/PC static optimisations (use JUMP_TB when possible)
7a3f1944 27 Optimize synthetic instructions
bd497938 28*/
7a3f1944
FB
29
30#include <stdarg.h>
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <inttypes.h>
35
36#include "cpu.h"
37#include "exec-all.h"
38#include "disas.h"
57fec1fe 39#include "tcg-op.h"
7a3f1944
FB
40
41#define DEBUG_DISAS
42
72cbca10
FB
43#define DYNAMIC_PC 1 /* dynamic pc value */
44#define JUMP_PC 2 /* dynamic pc value which takes only two values
45 according to jump_pc[T2] */
46
7a3f1944 47typedef struct DisasContext {
0f8a249a
BS
48 target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
49 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
72cbca10 50 target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
cf495bcf 51 int is_br;
e8af50a3 52 int mem_idx;
a80dde08 53 int fpu_enabled;
cf495bcf 54 struct TranslationBlock *tb;
7a3f1944
FB
55} DisasContext;
56
aaed909a
FB
57typedef struct sparc_def_t sparc_def_t;
58
62724a37
BS
59struct sparc_def_t {
60 const unsigned char *name;
61 target_ulong iu_version;
62 uint32_t fpu_version;
63 uint32_t mmu_version;
6d5f237a 64 uint32_t mmu_bm;
3deaeab7
BS
65 uint32_t mmu_ctpr_mask;
66 uint32_t mmu_cxr_mask;
67 uint32_t mmu_sfsr_mask;
68 uint32_t mmu_trcr_mask;
62724a37
BS
69};
70
aaed909a
FB
71static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name);
72
7a3f1944
FB
73extern FILE *logfile;
74extern int loglevel;
75
3475187d 76// This function uses non-native bit order
7a3f1944
FB
77#define GET_FIELD(X, FROM, TO) \
78 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
79
3475187d
FB
80// This function uses the order in the manuals, i.e. bit 0 is 2^0
81#define GET_FIELD_SP(X, FROM, TO) \
82 GET_FIELD(X, 31 - (TO), 31 - (FROM))
83
84#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
46d38ba8 85#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
3475187d
FB
86
87#ifdef TARGET_SPARC64
0387d928 88#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
1f587329 89#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
3475187d 90#else
c185970a 91#define DFPREG(r) (r & 0x1e)
1f587329 92#define QFPREG(r) (r & 0x1c)
3475187d
FB
93#endif
94
95static int sign_extend(int x, int len)
96{
97 len = 32 - len;
98 return (x << len) >> len;
99}
100
7a3f1944
FB
101#define IS_IMM (insn & (1<<13))
102
cf495bcf 103static void disas_sparc_insn(DisasContext * dc);
7a3f1944 104
a68156d0 105static GenOpFunc * const gen_op_movl_TN_reg[2][32] = {
cf495bcf
FB
106 {
107 gen_op_movl_g0_T0,
108 gen_op_movl_g1_T0,
109 gen_op_movl_g2_T0,
110 gen_op_movl_g3_T0,
111 gen_op_movl_g4_T0,
112 gen_op_movl_g5_T0,
113 gen_op_movl_g6_T0,
114 gen_op_movl_g7_T0,
115 gen_op_movl_o0_T0,
116 gen_op_movl_o1_T0,
117 gen_op_movl_o2_T0,
118 gen_op_movl_o3_T0,
119 gen_op_movl_o4_T0,
120 gen_op_movl_o5_T0,
121 gen_op_movl_o6_T0,
122 gen_op_movl_o7_T0,
123 gen_op_movl_l0_T0,
124 gen_op_movl_l1_T0,
125 gen_op_movl_l2_T0,
126 gen_op_movl_l3_T0,
127 gen_op_movl_l4_T0,
128 gen_op_movl_l5_T0,
129 gen_op_movl_l6_T0,
130 gen_op_movl_l7_T0,
131 gen_op_movl_i0_T0,
132 gen_op_movl_i1_T0,
133 gen_op_movl_i2_T0,
134 gen_op_movl_i3_T0,
135 gen_op_movl_i4_T0,
136 gen_op_movl_i5_T0,
137 gen_op_movl_i6_T0,
138 gen_op_movl_i7_T0,
139 },
140 {
141 gen_op_movl_g0_T1,
142 gen_op_movl_g1_T1,
143 gen_op_movl_g2_T1,
144 gen_op_movl_g3_T1,
145 gen_op_movl_g4_T1,
146 gen_op_movl_g5_T1,
147 gen_op_movl_g6_T1,
148 gen_op_movl_g7_T1,
149 gen_op_movl_o0_T1,
150 gen_op_movl_o1_T1,
151 gen_op_movl_o2_T1,
152 gen_op_movl_o3_T1,
153 gen_op_movl_o4_T1,
154 gen_op_movl_o5_T1,
155 gen_op_movl_o6_T1,
156 gen_op_movl_o7_T1,
157 gen_op_movl_l0_T1,
158 gen_op_movl_l1_T1,
159 gen_op_movl_l2_T1,
160 gen_op_movl_l3_T1,
161 gen_op_movl_l4_T1,
162 gen_op_movl_l5_T1,
163 gen_op_movl_l6_T1,
164 gen_op_movl_l7_T1,
165 gen_op_movl_i0_T1,
166 gen_op_movl_i1_T1,
167 gen_op_movl_i2_T1,
168 gen_op_movl_i3_T1,
169 gen_op_movl_i4_T1,
170 gen_op_movl_i5_T1,
171 gen_op_movl_i6_T1,
172 gen_op_movl_i7_T1,
173 }
7a3f1944
FB
174};
175
a68156d0 176static GenOpFunc * const gen_op_movl_reg_TN[3][32] = {
cf495bcf
FB
177 {
178 gen_op_movl_T0_g0,
179 gen_op_movl_T0_g1,
180 gen_op_movl_T0_g2,
181 gen_op_movl_T0_g3,
182 gen_op_movl_T0_g4,
183 gen_op_movl_T0_g5,
184 gen_op_movl_T0_g6,
185 gen_op_movl_T0_g7,
186 gen_op_movl_T0_o0,
187 gen_op_movl_T0_o1,
188 gen_op_movl_T0_o2,
189 gen_op_movl_T0_o3,
190 gen_op_movl_T0_o4,
191 gen_op_movl_T0_o5,
192 gen_op_movl_T0_o6,
193 gen_op_movl_T0_o7,
194 gen_op_movl_T0_l0,
195 gen_op_movl_T0_l1,
196 gen_op_movl_T0_l2,
197 gen_op_movl_T0_l3,
198 gen_op_movl_T0_l4,
199 gen_op_movl_T0_l5,
200 gen_op_movl_T0_l6,
201 gen_op_movl_T0_l7,
202 gen_op_movl_T0_i0,
203 gen_op_movl_T0_i1,
204 gen_op_movl_T0_i2,
205 gen_op_movl_T0_i3,
206 gen_op_movl_T0_i4,
207 gen_op_movl_T0_i5,
208 gen_op_movl_T0_i6,
209 gen_op_movl_T0_i7,
210 },
211 {
212 gen_op_movl_T1_g0,
213 gen_op_movl_T1_g1,
214 gen_op_movl_T1_g2,
215 gen_op_movl_T1_g3,
216 gen_op_movl_T1_g4,
217 gen_op_movl_T1_g5,
218 gen_op_movl_T1_g6,
219 gen_op_movl_T1_g7,
220 gen_op_movl_T1_o0,
221 gen_op_movl_T1_o1,
222 gen_op_movl_T1_o2,
223 gen_op_movl_T1_o3,
224 gen_op_movl_T1_o4,
225 gen_op_movl_T1_o5,
226 gen_op_movl_T1_o6,
227 gen_op_movl_T1_o7,
228 gen_op_movl_T1_l0,
229 gen_op_movl_T1_l1,
230 gen_op_movl_T1_l2,
231 gen_op_movl_T1_l3,
232 gen_op_movl_T1_l4,
233 gen_op_movl_T1_l5,
234 gen_op_movl_T1_l6,
235 gen_op_movl_T1_l7,
236 gen_op_movl_T1_i0,
237 gen_op_movl_T1_i1,
238 gen_op_movl_T1_i2,
239 gen_op_movl_T1_i3,
240 gen_op_movl_T1_i4,
241 gen_op_movl_T1_i5,
242 gen_op_movl_T1_i6,
243 gen_op_movl_T1_i7,
244 },
245 {
246 gen_op_movl_T2_g0,
247 gen_op_movl_T2_g1,
248 gen_op_movl_T2_g2,
249 gen_op_movl_T2_g3,
250 gen_op_movl_T2_g4,
251 gen_op_movl_T2_g5,
252 gen_op_movl_T2_g6,
253 gen_op_movl_T2_g7,
254 gen_op_movl_T2_o0,
255 gen_op_movl_T2_o1,
256 gen_op_movl_T2_o2,
257 gen_op_movl_T2_o3,
258 gen_op_movl_T2_o4,
259 gen_op_movl_T2_o5,
260 gen_op_movl_T2_o6,
261 gen_op_movl_T2_o7,
262 gen_op_movl_T2_l0,
263 gen_op_movl_T2_l1,
264 gen_op_movl_T2_l2,
265 gen_op_movl_T2_l3,
266 gen_op_movl_T2_l4,
267 gen_op_movl_T2_l5,
268 gen_op_movl_T2_l6,
269 gen_op_movl_T2_l7,
270 gen_op_movl_T2_i0,
271 gen_op_movl_T2_i1,
272 gen_op_movl_T2_i2,
273 gen_op_movl_T2_i3,
274 gen_op_movl_T2_i4,
275 gen_op_movl_T2_i5,
276 gen_op_movl_T2_i6,
277 gen_op_movl_T2_i7,
278 }
7a3f1944
FB
279};
280
a68156d0 281static GenOpFunc1 * const gen_op_movl_TN_im[3] = {
cf495bcf
FB
282 gen_op_movl_T0_im,
283 gen_op_movl_T1_im,
284 gen_op_movl_T2_im
7a3f1944
FB
285};
286
3475187d
FB
287// Sign extending version
288static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
289 gen_op_movl_T0_sim,
290 gen_op_movl_T1_sim,
291 gen_op_movl_T2_sim
292};
293
294#ifdef TARGET_SPARC64
295#define GEN32(func, NAME) \
a68156d0 296static GenOpFunc * const NAME ## _table [64] = { \
3475187d
FB
297NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
298NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
299NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
300NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
301NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
302NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
303NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
304NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
305NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0, \
306NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0, \
307NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0, \
308NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0, \
309}; \
310static inline void func(int n) \
311{ \
312 NAME ## _table[n](); \
313}
314#else
e8af50a3 315#define GEN32(func, NAME) \
a68156d0 316static GenOpFunc *const NAME ## _table [32] = { \
e8af50a3
FB
317NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
318NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
319NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
320NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
321NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
322NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
323NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
324NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
325}; \
326static inline void func(int n) \
327{ \
328 NAME ## _table[n](); \
329}
3475187d 330#endif
e8af50a3
FB
331
332/* floating point registers moves */
333GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
334GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
e8af50a3
FB
335GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
336GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
e8af50a3
FB
337
338GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
339GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
e8af50a3
FB
340GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
341GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
e8af50a3 342
1f587329
BS
343#if defined(CONFIG_USER_ONLY)
344GEN32(gen_op_load_fpr_QT0, gen_op_load_fpr_QT0_fprf);
345GEN32(gen_op_load_fpr_QT1, gen_op_load_fpr_QT1_fprf);
346GEN32(gen_op_store_QT0_fpr, gen_op_store_QT0_fpr_fprf);
347GEN32(gen_op_store_QT1_fpr, gen_op_store_QT1_fpr_fprf);
348#endif
349
81ad8ba2
BS
350/* moves */
351#ifdef CONFIG_USER_ONLY
3475187d 352#define supervisor(dc) 0
81ad8ba2 353#ifdef TARGET_SPARC64
e9ebed4d 354#define hypervisor(dc) 0
81ad8ba2 355#endif
3475187d 356#define gen_op_ldst(name) gen_op_##name##_raw()
3475187d 357#else
6f27aba6 358#define supervisor(dc) (dc->mem_idx >= 1)
81ad8ba2
BS
359#ifdef TARGET_SPARC64
360#define hypervisor(dc) (dc->mem_idx == 2)
6f27aba6
BS
361#define OP_LD_TABLE(width) \
362 static GenOpFunc * const gen_op_##width[] = { \
363 &gen_op_##width##_user, \
364 &gen_op_##width##_kernel, \
365 &gen_op_##width##_hypv, \
366 };
367#else
0f8a249a 368#define OP_LD_TABLE(width) \
a68156d0 369 static GenOpFunc * const gen_op_##width[] = { \
0f8a249a
BS
370 &gen_op_##width##_user, \
371 &gen_op_##width##_kernel, \
81ad8ba2 372 };
3475187d 373#endif
6f27aba6
BS
374#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
375#endif
e8af50a3 376
81ad8ba2 377#ifndef CONFIG_USER_ONLY
e8af50a3
FB
378OP_LD_TABLE(ld);
379OP_LD_TABLE(st);
380OP_LD_TABLE(ldub);
381OP_LD_TABLE(lduh);
382OP_LD_TABLE(ldsb);
383OP_LD_TABLE(ldsh);
384OP_LD_TABLE(stb);
385OP_LD_TABLE(sth);
386OP_LD_TABLE(std);
387OP_LD_TABLE(ldstub);
388OP_LD_TABLE(swap);
389OP_LD_TABLE(ldd);
390OP_LD_TABLE(stf);
391OP_LD_TABLE(stdf);
392OP_LD_TABLE(ldf);
393OP_LD_TABLE(lddf);
394
3475187d 395#ifdef TARGET_SPARC64
dc011987 396OP_LD_TABLE(lduw);
3475187d
FB
397OP_LD_TABLE(ldsw);
398OP_LD_TABLE(ldx);
399OP_LD_TABLE(stx);
81ad8ba2
BS
400#endif
401#endif
402
403/* asi moves */
404#ifdef TARGET_SPARC64
405static inline void gen_ld_asi(int insn, int size, int sign)
406{
407 int asi, offset;
408
409 if (IS_IMM) {
410 offset = GET_FIELD(insn, 25, 31);
411 gen_op_ld_asi_reg(offset, size, sign);
412 } else {
413 asi = GET_FIELD(insn, 19, 26);
414 gen_op_ld_asi(asi, size, sign);
415 }
416}
417
418static inline void gen_st_asi(int insn, int size)
419{
420 int asi, offset;
421
422 if (IS_IMM) {
423 offset = GET_FIELD(insn, 25, 31);
424 gen_op_st_asi_reg(offset, size);
425 } else {
426 asi = GET_FIELD(insn, 19, 26);
427 gen_op_st_asi(asi, size);
428 }
429}
430
2382dc6b 431static inline void gen_ldf_asi(int insn, int size, int rd)
3391c818 432{
2382dc6b 433 int asi, offset;
3391c818 434
3391c818
BS
435 if (IS_IMM) {
436 offset = GET_FIELD(insn, 25, 31);
437 gen_op_ldf_asi_reg(offset, size, rd);
438 } else {
439 asi = GET_FIELD(insn, 19, 26);
440 gen_op_ldf_asi(asi, size, rd);
441 }
442}
443
2382dc6b 444static inline void gen_stf_asi(int insn, int size, int rd)
3391c818 445{
2382dc6b 446 int asi, offset;
3391c818 447
3391c818
BS
448 if (IS_IMM) {
449 offset = GET_FIELD(insn, 25, 31);
450 gen_op_stf_asi_reg(offset, size, rd);
451 } else {
452 asi = GET_FIELD(insn, 19, 26);
453 gen_op_stf_asi(asi, size, rd);
454 }
455}
456
81ad8ba2
BS
457static inline void gen_swap_asi(int insn)
458{
459 int asi, offset;
460
461 if (IS_IMM) {
462 offset = GET_FIELD(insn, 25, 31);
463 gen_op_swap_asi_reg(offset);
464 } else {
465 asi = GET_FIELD(insn, 19, 26);
466 gen_op_swap_asi(asi);
467 }
468}
469
470static inline void gen_ldstub_asi(int insn)
471{
472 int asi, offset;
473
474 if (IS_IMM) {
475 offset = GET_FIELD(insn, 25, 31);
476 gen_op_ldstub_asi_reg(offset);
477 } else {
478 asi = GET_FIELD(insn, 19, 26);
479 gen_op_ldstub_asi(asi);
480 }
481}
482
483static inline void gen_ldda_asi(int insn)
484{
485 int asi, offset;
486
487 if (IS_IMM) {
488 offset = GET_FIELD(insn, 25, 31);
489 gen_op_ldda_asi_reg(offset);
490 } else {
491 asi = GET_FIELD(insn, 19, 26);
492 gen_op_ldda_asi(asi);
493 }
494}
495
496static inline void gen_stda_asi(int insn)
497{
498 int asi, offset;
499
500 if (IS_IMM) {
501 offset = GET_FIELD(insn, 25, 31);
502 gen_op_stda_asi_reg(offset);
503 } else {
504 asi = GET_FIELD(insn, 19, 26);
505 gen_op_stda_asi(asi);
506 }
507}
508
509static inline void gen_cas_asi(int insn)
510{
511 int asi, offset;
512
513 if (IS_IMM) {
514 offset = GET_FIELD(insn, 25, 31);
515 gen_op_cas_asi_reg(offset);
516 } else {
517 asi = GET_FIELD(insn, 19, 26);
518 gen_op_cas_asi(asi);
519 }
520}
521
522static inline void gen_casx_asi(int insn)
523{
524 int asi, offset;
525
526 if (IS_IMM) {
527 offset = GET_FIELD(insn, 25, 31);
528 gen_op_casx_asi_reg(offset);
529 } else {
530 asi = GET_FIELD(insn, 19, 26);
531 gen_op_casx_asi(asi);
532 }
533}
534
535#elif !defined(CONFIG_USER_ONLY)
536
537static inline void gen_ld_asi(int insn, int size, int sign)
538{
539 int asi;
540
541 asi = GET_FIELD(insn, 19, 26);
542 gen_op_ld_asi(asi, size, sign);
543}
544
545static inline void gen_st_asi(int insn, int size)
546{
547 int asi;
548
549 asi = GET_FIELD(insn, 19, 26);
550 gen_op_st_asi(asi, size);
551}
552
553static inline void gen_ldstub_asi(int insn)
554{
555 int asi;
556
557 asi = GET_FIELD(insn, 19, 26);
558 gen_op_ldstub_asi(asi);
559}
560
561static inline void gen_swap_asi(int insn)
562{
563 int asi;
564
565 asi = GET_FIELD(insn, 19, 26);
566 gen_op_swap_asi(asi);
567}
568
569static inline void gen_ldda_asi(int insn)
570{
571 int asi;
572
573 asi = GET_FIELD(insn, 19, 26);
574 gen_op_ld_asi(asi, 8, 0);
575}
576
577static inline void gen_stda_asi(int insn)
578{
579 int asi;
580
581 asi = GET_FIELD(insn, 19, 26);
582 gen_op_st_asi(asi, 8);
583}
3475187d
FB
584#endif
585
586static inline void gen_movl_imm_TN(int reg, uint32_t imm)
7a3f1944 587{
83469015 588 gen_op_movl_TN_im[reg](imm);
7a3f1944
FB
589}
590
3475187d 591static inline void gen_movl_imm_T1(uint32_t val)
7a3f1944 592{
cf495bcf 593 gen_movl_imm_TN(1, val);
7a3f1944
FB
594}
595
3475187d 596static inline void gen_movl_imm_T0(uint32_t val)
7a3f1944 597{
cf495bcf 598 gen_movl_imm_TN(0, val);
7a3f1944
FB
599}
600
3475187d
FB
601static inline void gen_movl_simm_TN(int reg, int32_t imm)
602{
603 gen_op_movl_TN_sim[reg](imm);
604}
605
606static inline void gen_movl_simm_T1(int32_t val)
607{
608 gen_movl_simm_TN(1, val);
609}
610
611static inline void gen_movl_simm_T0(int32_t val)
612{
613 gen_movl_simm_TN(0, val);
614}
615
cf495bcf 616static inline void gen_movl_reg_TN(int reg, int t)
7a3f1944 617{
cf495bcf 618 if (reg)
0f8a249a 619 gen_op_movl_reg_TN[t][reg] ();
cf495bcf 620 else
0f8a249a 621 gen_movl_imm_TN(t, 0);
7a3f1944
FB
622}
623
cf495bcf 624static inline void gen_movl_reg_T0(int reg)
7a3f1944 625{
cf495bcf 626 gen_movl_reg_TN(reg, 0);
7a3f1944
FB
627}
628
cf495bcf 629static inline void gen_movl_reg_T1(int reg)
7a3f1944 630{
cf495bcf 631 gen_movl_reg_TN(reg, 1);
7a3f1944
FB
632}
633
cf495bcf 634static inline void gen_movl_reg_T2(int reg)
7a3f1944 635{
cf495bcf 636 gen_movl_reg_TN(reg, 2);
7a3f1944
FB
637}
638
cf495bcf 639static inline void gen_movl_TN_reg(int reg, int t)
7a3f1944 640{
cf495bcf 641 if (reg)
0f8a249a 642 gen_op_movl_TN_reg[t][reg] ();
7a3f1944
FB
643}
644
cf495bcf 645static inline void gen_movl_T0_reg(int reg)
7a3f1944 646{
cf495bcf 647 gen_movl_TN_reg(reg, 0);
7a3f1944
FB
648}
649
cf495bcf 650static inline void gen_movl_T1_reg(int reg)
7a3f1944 651{
cf495bcf 652 gen_movl_TN_reg(reg, 1);
7a3f1944
FB
653}
654
3475187d
FB
655static inline void gen_jmp_im(target_ulong pc)
656{
657#ifdef TARGET_SPARC64
658 if (pc == (uint32_t)pc) {
659 gen_op_jmp_im(pc);
660 } else {
661 gen_op_jmp_im64(pc >> 32, pc);
662 }
663#else
664 gen_op_jmp_im(pc);
665#endif
666}
667
668static inline void gen_movl_npc_im(target_ulong npc)
669{
670#ifdef TARGET_SPARC64
671 if (npc == (uint32_t)npc) {
672 gen_op_movl_npc_im(npc);
673 } else {
674 gen_op_movq_npc_im64(npc >> 32, npc);
675 }
676#else
677 gen_op_movl_npc_im(npc);
678#endif
679}
680
5fafdf24 681static inline void gen_goto_tb(DisasContext *s, int tb_num,
6e256c93
FB
682 target_ulong pc, target_ulong npc)
683{
684 TranslationBlock *tb;
685
686 tb = s->tb;
687 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
688 (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) {
689 /* jump to same page: we can use a direct jump */
57fec1fe 690 tcg_gen_goto_tb(tb_num);
6e256c93
FB
691 gen_jmp_im(pc);
692 gen_movl_npc_im(npc);
57fec1fe 693 tcg_gen_exit_tb((long)tb + tb_num);
6e256c93
FB
694 } else {
695 /* jump to another page: currently not optimized */
696 gen_jmp_im(pc);
697 gen_movl_npc_im(npc);
57fec1fe 698 tcg_gen_exit_tb(0);
6e256c93
FB
699 }
700}
701
46525e1f
BS
702static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
703 target_ulong pc2)
83469015
FB
704{
705 int l1;
706
707 l1 = gen_new_label();
708
709 gen_op_jz_T2_label(l1);
710
6e256c93 711 gen_goto_tb(dc, 0, pc1, pc1 + 4);
83469015
FB
712
713 gen_set_label(l1);
6e256c93 714 gen_goto_tb(dc, 1, pc2, pc2 + 4);
83469015
FB
715}
716
46525e1f
BS
717static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
718 target_ulong pc2)
83469015
FB
719{
720 int l1;
721
722 l1 = gen_new_label();
723
724 gen_op_jz_T2_label(l1);
725
6e256c93 726 gen_goto_tb(dc, 0, pc2, pc1);
83469015
FB
727
728 gen_set_label(l1);
6e256c93 729 gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
83469015
FB
730}
731
46525e1f
BS
732static inline void gen_branch(DisasContext *dc, target_ulong pc,
733 target_ulong npc)
83469015 734{
6e256c93 735 gen_goto_tb(dc, 0, pc, npc);
83469015
FB
736}
737
46525e1f 738static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2)
83469015
FB
739{
740 int l1, l2;
741
742 l1 = gen_new_label();
743 l2 = gen_new_label();
744 gen_op_jz_T2_label(l1);
745
746 gen_movl_npc_im(npc1);
747 gen_op_jmp_label(l2);
748
749 gen_set_label(l1);
750 gen_movl_npc_im(npc2);
751 gen_set_label(l2);
752}
753
754/* call this function before using T2 as it may have been set for a jump */
755static inline void flush_T2(DisasContext * dc)
756{
757 if (dc->npc == JUMP_PC) {
46525e1f 758 gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
83469015
FB
759 dc->npc = DYNAMIC_PC;
760 }
761}
762
72cbca10
FB
763static inline void save_npc(DisasContext * dc)
764{
765 if (dc->npc == JUMP_PC) {
46525e1f 766 gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
72cbca10
FB
767 dc->npc = DYNAMIC_PC;
768 } else if (dc->npc != DYNAMIC_PC) {
3475187d 769 gen_movl_npc_im(dc->npc);
72cbca10
FB
770 }
771}
772
773static inline void save_state(DisasContext * dc)
774{
3475187d 775 gen_jmp_im(dc->pc);
72cbca10
FB
776 save_npc(dc);
777}
778
0bee699e
FB
779static inline void gen_mov_pc_npc(DisasContext * dc)
780{
781 if (dc->npc == JUMP_PC) {
46525e1f 782 gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
0bee699e
FB
783 gen_op_mov_pc_npc();
784 dc->pc = DYNAMIC_PC;
785 } else if (dc->npc == DYNAMIC_PC) {
786 gen_op_mov_pc_npc();
787 dc->pc = DYNAMIC_PC;
788 } else {
789 dc->pc = dc->npc;
790 }
791}
792
3475187d
FB
793static GenOpFunc * const gen_cond[2][16] = {
794 {
0f8a249a
BS
795 gen_op_eval_bn,
796 gen_op_eval_be,
797 gen_op_eval_ble,
798 gen_op_eval_bl,
799 gen_op_eval_bleu,
800 gen_op_eval_bcs,
801 gen_op_eval_bneg,
802 gen_op_eval_bvs,
803 gen_op_eval_ba,
804 gen_op_eval_bne,
805 gen_op_eval_bg,
806 gen_op_eval_bge,
807 gen_op_eval_bgu,
808 gen_op_eval_bcc,
809 gen_op_eval_bpos,
810 gen_op_eval_bvc,
3475187d
FB
811 },
812 {
813#ifdef TARGET_SPARC64
0f8a249a
BS
814 gen_op_eval_bn,
815 gen_op_eval_xbe,
816 gen_op_eval_xble,
817 gen_op_eval_xbl,
818 gen_op_eval_xbleu,
819 gen_op_eval_xbcs,
820 gen_op_eval_xbneg,
821 gen_op_eval_xbvs,
822 gen_op_eval_ba,
823 gen_op_eval_xbne,
824 gen_op_eval_xbg,
825 gen_op_eval_xbge,
826 gen_op_eval_xbgu,
827 gen_op_eval_xbcc,
828 gen_op_eval_xbpos,
829 gen_op_eval_xbvc,
3475187d
FB
830#endif
831 },
832};
833
834static GenOpFunc * const gen_fcond[4][16] = {
835 {
0f8a249a
BS
836 gen_op_eval_bn,
837 gen_op_eval_fbne,
838 gen_op_eval_fblg,
839 gen_op_eval_fbul,
840 gen_op_eval_fbl,
841 gen_op_eval_fbug,
842 gen_op_eval_fbg,
843 gen_op_eval_fbu,
844 gen_op_eval_ba,
845 gen_op_eval_fbe,
846 gen_op_eval_fbue,
847 gen_op_eval_fbge,
848 gen_op_eval_fbuge,
849 gen_op_eval_fble,
850 gen_op_eval_fbule,
851 gen_op_eval_fbo,
3475187d
FB
852 },
853#ifdef TARGET_SPARC64
854 {
0f8a249a
BS
855 gen_op_eval_bn,
856 gen_op_eval_fbne_fcc1,
857 gen_op_eval_fblg_fcc1,
858 gen_op_eval_fbul_fcc1,
859 gen_op_eval_fbl_fcc1,
860 gen_op_eval_fbug_fcc1,
861 gen_op_eval_fbg_fcc1,
862 gen_op_eval_fbu_fcc1,
863 gen_op_eval_ba,
864 gen_op_eval_fbe_fcc1,
865 gen_op_eval_fbue_fcc1,
866 gen_op_eval_fbge_fcc1,
867 gen_op_eval_fbuge_fcc1,
868 gen_op_eval_fble_fcc1,
869 gen_op_eval_fbule_fcc1,
870 gen_op_eval_fbo_fcc1,
3475187d
FB
871 },
872 {
0f8a249a
BS
873 gen_op_eval_bn,
874 gen_op_eval_fbne_fcc2,
875 gen_op_eval_fblg_fcc2,
876 gen_op_eval_fbul_fcc2,
877 gen_op_eval_fbl_fcc2,
878 gen_op_eval_fbug_fcc2,
879 gen_op_eval_fbg_fcc2,
880 gen_op_eval_fbu_fcc2,
881 gen_op_eval_ba,
882 gen_op_eval_fbe_fcc2,
883 gen_op_eval_fbue_fcc2,
884 gen_op_eval_fbge_fcc2,
885 gen_op_eval_fbuge_fcc2,
886 gen_op_eval_fble_fcc2,
887 gen_op_eval_fbule_fcc2,
888 gen_op_eval_fbo_fcc2,
3475187d
FB
889 },
890 {
0f8a249a
BS
891 gen_op_eval_bn,
892 gen_op_eval_fbne_fcc3,
893 gen_op_eval_fblg_fcc3,
894 gen_op_eval_fbul_fcc3,
895 gen_op_eval_fbl_fcc3,
896 gen_op_eval_fbug_fcc3,
897 gen_op_eval_fbg_fcc3,
898 gen_op_eval_fbu_fcc3,
899 gen_op_eval_ba,
900 gen_op_eval_fbe_fcc3,
901 gen_op_eval_fbue_fcc3,
902 gen_op_eval_fbge_fcc3,
903 gen_op_eval_fbuge_fcc3,
904 gen_op_eval_fble_fcc3,
905 gen_op_eval_fbule_fcc3,
906 gen_op_eval_fbo_fcc3,
3475187d
FB
907 },
908#else
909 {}, {}, {},
910#endif
911};
7a3f1944 912
3475187d
FB
913#ifdef TARGET_SPARC64
914static void gen_cond_reg(int cond)
e8af50a3 915{
0f8a249a
BS
916 switch (cond) {
917 case 0x1:
918 gen_op_eval_brz();
919 break;
920 case 0x2:
921 gen_op_eval_brlez();
922 break;
923 case 0x3:
924 gen_op_eval_brlz();
925 break;
926 case 0x5:
927 gen_op_eval_brnz();
928 break;
929 case 0x6:
930 gen_op_eval_brgz();
931 break;
e8af50a3 932 default:
0f8a249a
BS
933 case 0x7:
934 gen_op_eval_brgez();
935 break;
936 }
e8af50a3 937}
3475187d 938#endif
cf495bcf 939
0bee699e 940/* XXX: potentially incorrect if dynamic npc */
3475187d 941static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
7a3f1944 942{
cf495bcf 943 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
af7bf89b 944 target_ulong target = dc->pc + offset;
5fafdf24 945
cf495bcf 946 if (cond == 0x0) {
0f8a249a
BS
947 /* unconditional not taken */
948 if (a) {
949 dc->pc = dc->npc + 4;
950 dc->npc = dc->pc + 4;
951 } else {
952 dc->pc = dc->npc;
953 dc->npc = dc->pc + 4;
954 }
cf495bcf 955 } else if (cond == 0x8) {
0f8a249a
BS
956 /* unconditional taken */
957 if (a) {
958 dc->pc = target;
959 dc->npc = dc->pc + 4;
960 } else {
961 dc->pc = dc->npc;
962 dc->npc = target;
963 }
cf495bcf 964 } else {
72cbca10 965 flush_T2(dc);
3475187d 966 gen_cond[cc][cond]();
0f8a249a
BS
967 if (a) {
968 gen_branch_a(dc, target, dc->npc);
cf495bcf 969 dc->is_br = 1;
0f8a249a 970 } else {
cf495bcf 971 dc->pc = dc->npc;
72cbca10
FB
972 dc->jump_pc[0] = target;
973 dc->jump_pc[1] = dc->npc + 4;
974 dc->npc = JUMP_PC;
0f8a249a 975 }
cf495bcf 976 }
7a3f1944
FB
977}
978
0bee699e 979/* XXX: potentially incorrect if dynamic npc */
3475187d 980static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
e8af50a3
FB
981{
982 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
af7bf89b
FB
983 target_ulong target = dc->pc + offset;
984
e8af50a3 985 if (cond == 0x0) {
0f8a249a
BS
986 /* unconditional not taken */
987 if (a) {
988 dc->pc = dc->npc + 4;
989 dc->npc = dc->pc + 4;
990 } else {
991 dc->pc = dc->npc;
992 dc->npc = dc->pc + 4;
993 }
e8af50a3 994 } else if (cond == 0x8) {
0f8a249a
BS
995 /* unconditional taken */
996 if (a) {
997 dc->pc = target;
998 dc->npc = dc->pc + 4;
999 } else {
1000 dc->pc = dc->npc;
1001 dc->npc = target;
1002 }
e8af50a3
FB
1003 } else {
1004 flush_T2(dc);
3475187d 1005 gen_fcond[cc][cond]();
0f8a249a
BS
1006 if (a) {
1007 gen_branch_a(dc, target, dc->npc);
e8af50a3 1008 dc->is_br = 1;
0f8a249a 1009 } else {
e8af50a3
FB
1010 dc->pc = dc->npc;
1011 dc->jump_pc[0] = target;
1012 dc->jump_pc[1] = dc->npc + 4;
1013 dc->npc = JUMP_PC;
0f8a249a 1014 }
e8af50a3
FB
1015 }
1016}
1017
3475187d
FB
1018#ifdef TARGET_SPARC64
1019/* XXX: potentially incorrect if dynamic npc */
1020static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
7a3f1944 1021{
3475187d
FB
1022 unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
1023 target_ulong target = dc->pc + offset;
1024
1025 flush_T2(dc);
1026 gen_cond_reg(cond);
1027 if (a) {
0f8a249a
BS
1028 gen_branch_a(dc, target, dc->npc);
1029 dc->is_br = 1;
3475187d 1030 } else {
0f8a249a
BS
1031 dc->pc = dc->npc;
1032 dc->jump_pc[0] = target;
1033 dc->jump_pc[1] = dc->npc + 4;
1034 dc->npc = JUMP_PC;
3475187d 1035 }
7a3f1944
FB
1036}
1037
3475187d
FB
1038static GenOpFunc * const gen_fcmps[4] = {
1039 gen_op_fcmps,
1040 gen_op_fcmps_fcc1,
1041 gen_op_fcmps_fcc2,
1042 gen_op_fcmps_fcc3,
1043};
1044
1045static GenOpFunc * const gen_fcmpd[4] = {
1046 gen_op_fcmpd,
1047 gen_op_fcmpd_fcc1,
1048 gen_op_fcmpd_fcc2,
1049 gen_op_fcmpd_fcc3,
1050};
417454b0 1051
1f587329
BS
1052#if defined(CONFIG_USER_ONLY)
1053static GenOpFunc * const gen_fcmpq[4] = {
1054 gen_op_fcmpq,
1055 gen_op_fcmpq_fcc1,
1056 gen_op_fcmpq_fcc2,
1057 gen_op_fcmpq_fcc3,
1058};
1059#endif
1060
417454b0
BS
1061static GenOpFunc * const gen_fcmpes[4] = {
1062 gen_op_fcmpes,
1063 gen_op_fcmpes_fcc1,
1064 gen_op_fcmpes_fcc2,
1065 gen_op_fcmpes_fcc3,
1066};
1067
1068static GenOpFunc * const gen_fcmped[4] = {
1069 gen_op_fcmped,
1070 gen_op_fcmped_fcc1,
1071 gen_op_fcmped_fcc2,
1072 gen_op_fcmped_fcc3,
1073};
1074
1f587329
BS
1075#if defined(CONFIG_USER_ONLY)
1076static GenOpFunc * const gen_fcmpeq[4] = {
1077 gen_op_fcmpeq,
1078 gen_op_fcmpeq_fcc1,
1079 gen_op_fcmpeq_fcc2,
1080 gen_op_fcmpeq_fcc3,
1081};
1082#endif
3475187d
FB
1083#endif
1084
a80dde08
FB
1085static int gen_trap_ifnofpu(DisasContext * dc)
1086{
1087#if !defined(CONFIG_USER_ONLY)
1088 if (!dc->fpu_enabled) {
1089 save_state(dc);
1090 gen_op_exception(TT_NFPU_INSN);
1091 dc->is_br = 1;
1092 return 1;
1093 }
1094#endif
1095 return 0;
1096}
1097
0bee699e 1098/* before an instruction, dc->pc must be static */
cf495bcf
FB
1099static void disas_sparc_insn(DisasContext * dc)
1100{
1101 unsigned int insn, opc, rs1, rs2, rd;
7a3f1944 1102
0fa85d43 1103 insn = ldl_code(dc->pc);
cf495bcf 1104 opc = GET_FIELD(insn, 0, 1);
7a3f1944 1105
cf495bcf
FB
1106 rd = GET_FIELD(insn, 2, 6);
1107 switch (opc) {
0f8a249a
BS
1108 case 0: /* branches/sethi */
1109 {
1110 unsigned int xop = GET_FIELD(insn, 7, 9);
1111 int32_t target;
1112 switch (xop) {
3475187d 1113#ifdef TARGET_SPARC64
0f8a249a
BS
1114 case 0x1: /* V9 BPcc */
1115 {
1116 int cc;
1117
1118 target = GET_FIELD_SP(insn, 0, 18);
1119 target = sign_extend(target, 18);
1120 target <<= 2;
1121 cc = GET_FIELD_SP(insn, 20, 21);
1122 if (cc == 0)
1123 do_branch(dc, target, insn, 0);
1124 else if (cc == 2)
1125 do_branch(dc, target, insn, 1);
1126 else
1127 goto illegal_insn;
1128 goto jmp_insn;
1129 }
1130 case 0x3: /* V9 BPr */
1131 {
1132 target = GET_FIELD_SP(insn, 0, 13) |
13846e70 1133 (GET_FIELD_SP(insn, 20, 21) << 14);
0f8a249a
BS
1134 target = sign_extend(target, 16);
1135 target <<= 2;
1136 rs1 = GET_FIELD(insn, 13, 17);
1137 gen_movl_reg_T0(rs1);
1138 do_branch_reg(dc, target, insn);
1139 goto jmp_insn;
1140 }
1141 case 0x5: /* V9 FBPcc */
1142 {
1143 int cc = GET_FIELD_SP(insn, 20, 21);
a80dde08
FB
1144 if (gen_trap_ifnofpu(dc))
1145 goto jmp_insn;
0f8a249a
BS
1146 target = GET_FIELD_SP(insn, 0, 18);
1147 target = sign_extend(target, 19);
1148 target <<= 2;
1149 do_fbranch(dc, target, insn, cc);
1150 goto jmp_insn;
1151 }
a4d17f19 1152#else
0f8a249a
BS
1153 case 0x7: /* CBN+x */
1154 {
1155 goto ncp_insn;
1156 }
1157#endif
1158 case 0x2: /* BN+x */
1159 {
1160 target = GET_FIELD(insn, 10, 31);
1161 target = sign_extend(target, 22);
1162 target <<= 2;
1163 do_branch(dc, target, insn, 0);
1164 goto jmp_insn;
1165 }
1166 case 0x6: /* FBN+x */
1167 {
a80dde08
FB
1168 if (gen_trap_ifnofpu(dc))
1169 goto jmp_insn;
0f8a249a
BS
1170 target = GET_FIELD(insn, 10, 31);
1171 target = sign_extend(target, 22);
1172 target <<= 2;
1173 do_fbranch(dc, target, insn, 0);
1174 goto jmp_insn;
1175 }
1176 case 0x4: /* SETHI */
e80cfcfc
FB
1177#define OPTIM
1178#if defined(OPTIM)
0f8a249a 1179 if (rd) { // nop
e80cfcfc 1180#endif
0f8a249a
BS
1181 uint32_t value = GET_FIELD(insn, 10, 31);
1182 gen_movl_imm_T0(value << 10);
1183 gen_movl_T0_reg(rd);
e80cfcfc 1184#if defined(OPTIM)
0f8a249a 1185 }
e80cfcfc 1186#endif
0f8a249a
BS
1187 break;
1188 case 0x0: /* UNIMPL */
1189 default:
3475187d 1190 goto illegal_insn;
0f8a249a
BS
1191 }
1192 break;
1193 }
1194 break;
cf495bcf 1195 case 1:
0f8a249a
BS
1196 /*CALL*/ {
1197 target_long target = GET_FIELDs(insn, 2, 31) << 2;
cf495bcf 1198
83469015 1199#ifdef TARGET_SPARC64
0f8a249a
BS
1200 if (dc->pc == (uint32_t)dc->pc) {
1201 gen_op_movl_T0_im(dc->pc);
1202 } else {
1203 gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1204 }
83469015 1205#else
0f8a249a 1206 gen_op_movl_T0_im(dc->pc);
83469015 1207#endif
0f8a249a
BS
1208 gen_movl_T0_reg(15);
1209 target += dc->pc;
0bee699e 1210 gen_mov_pc_npc(dc);
0f8a249a
BS
1211 dc->npc = target;
1212 }
1213 goto jmp_insn;
1214 case 2: /* FPU & Logical Operations */
1215 {
1216 unsigned int xop = GET_FIELD(insn, 7, 12);
1217 if (xop == 0x3a) { /* generate trap */
cf495bcf 1218 int cond;
3475187d 1219
cf495bcf
FB
1220 rs1 = GET_FIELD(insn, 13, 17);
1221 gen_movl_reg_T0(rs1);
0f8a249a
BS
1222 if (IS_IMM) {
1223 rs2 = GET_FIELD(insn, 25, 31);
e80cfcfc 1224#if defined(OPTIM)
0f8a249a 1225 if (rs2 != 0) {
e80cfcfc 1226#endif
0f8a249a
BS
1227 gen_movl_simm_T1(rs2);
1228 gen_op_add_T1_T0();
e80cfcfc 1229#if defined(OPTIM)
0f8a249a 1230 }
e80cfcfc 1231#endif
cf495bcf
FB
1232 } else {
1233 rs2 = GET_FIELD(insn, 27, 31);
e80cfcfc 1234#if defined(OPTIM)
0f8a249a 1235 if (rs2 != 0) {
e80cfcfc 1236#endif
0f8a249a
BS
1237 gen_movl_reg_T1(rs2);
1238 gen_op_add_T1_T0();
e80cfcfc 1239#if defined(OPTIM)
0f8a249a 1240 }
e80cfcfc 1241#endif
cf495bcf 1242 }
cf495bcf
FB
1243 cond = GET_FIELD(insn, 3, 6);
1244 if (cond == 0x8) {
a80dde08 1245 save_state(dc);
cf495bcf 1246 gen_op_trap_T0();
af7bf89b 1247 } else if (cond != 0) {
3475187d 1248#ifdef TARGET_SPARC64
0f8a249a
BS
1249 /* V9 icc/xcc */
1250 int cc = GET_FIELD_SP(insn, 11, 12);
1251 flush_T2(dc);
a80dde08 1252 save_state(dc);
0f8a249a
BS
1253 if (cc == 0)
1254 gen_cond[0][cond]();
1255 else if (cc == 2)
1256 gen_cond[1][cond]();
1257 else
1258 goto illegal_insn;
3475187d 1259#else
0f8a249a 1260 flush_T2(dc);
a80dde08 1261 save_state(dc);
0f8a249a 1262 gen_cond[0][cond]();
3475187d 1263#endif
cf495bcf
FB
1264 gen_op_trapcc_T0();
1265 }
a80dde08 1266 gen_op_next_insn();
57fec1fe 1267 tcg_gen_exit_tb(0);
a80dde08
FB
1268 dc->is_br = 1;
1269 goto jmp_insn;
cf495bcf
FB
1270 } else if (xop == 0x28) {
1271 rs1 = GET_FIELD(insn, 13, 17);
1272 switch(rs1) {
1273 case 0: /* rdy */
65fe7b09
BS
1274#ifndef TARGET_SPARC64
1275 case 0x01 ... 0x0e: /* undefined in the SPARCv8
1276 manual, rdy on the microSPARC
1277 II */
1278 case 0x0f: /* stbar in the SPARCv8 manual,
1279 rdy on the microSPARC II */
1280 case 0x10 ... 0x1f: /* implementation-dependent in the
1281 SPARCv8 manual, rdy on the
1282 microSPARC II */
1283#endif
1284 gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
cf495bcf
FB
1285 gen_movl_T0_reg(rd);
1286 break;
3475187d 1287#ifdef TARGET_SPARC64
0f8a249a 1288 case 0x2: /* V9 rdccr */
3475187d
FB
1289 gen_op_rdccr();
1290 gen_movl_T0_reg(rd);
1291 break;
0f8a249a
BS
1292 case 0x3: /* V9 rdasi */
1293 gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
3475187d
FB
1294 gen_movl_T0_reg(rd);
1295 break;
0f8a249a 1296 case 0x4: /* V9 rdtick */
3475187d
FB
1297 gen_op_rdtick();
1298 gen_movl_T0_reg(rd);
1299 break;
0f8a249a
BS
1300 case 0x5: /* V9 rdpc */
1301 if (dc->pc == (uint32_t)dc->pc) {
1302 gen_op_movl_T0_im(dc->pc);
1303 } else {
1304 gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1305 }
1306 gen_movl_T0_reg(rd);
1307 break;
1308 case 0x6: /* V9 rdfprs */
1309 gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
3475187d
FB
1310 gen_movl_T0_reg(rd);
1311 break;
65fe7b09
BS
1312 case 0xf: /* V9 membar */
1313 break; /* no effect */
0f8a249a 1314 case 0x13: /* Graphics Status */
725cb90b
FB
1315 if (gen_trap_ifnofpu(dc))
1316 goto jmp_insn;
0f8a249a 1317 gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
725cb90b
FB
1318 gen_movl_T0_reg(rd);
1319 break;
0f8a249a
BS
1320 case 0x17: /* Tick compare */
1321 gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
83469015
FB
1322 gen_movl_T0_reg(rd);
1323 break;
0f8a249a 1324 case 0x18: /* System tick */
20c9f095 1325 gen_op_rdstick();
83469015
FB
1326 gen_movl_T0_reg(rd);
1327 break;
0f8a249a
BS
1328 case 0x19: /* System tick compare */
1329 gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
83469015
FB
1330 gen_movl_T0_reg(rd);
1331 break;
0f8a249a
BS
1332 case 0x10: /* Performance Control */
1333 case 0x11: /* Performance Instrumentation Counter */
1334 case 0x12: /* Dispatch Control */
1335 case 0x14: /* Softint set, WO */
1336 case 0x15: /* Softint clear, WO */
1337 case 0x16: /* Softint write */
3475187d
FB
1338#endif
1339 default:
cf495bcf
FB
1340 goto illegal_insn;
1341 }
e8af50a3 1342#if !defined(CONFIG_USER_ONLY)
e9ebed4d 1343 } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
3475187d 1344#ifndef TARGET_SPARC64
0f8a249a
BS
1345 if (!supervisor(dc))
1346 goto priv_insn;
e8af50a3 1347 gen_op_rdpsr();
e9ebed4d
BS
1348#else
1349 if (!hypervisor(dc))
1350 goto priv_insn;
1351 rs1 = GET_FIELD(insn, 13, 17);
1352 switch (rs1) {
1353 case 0: // hpstate
1354 // gen_op_rdhpstate();
1355 break;
1356 case 1: // htstate
1357 // gen_op_rdhtstate();
1358 break;
1359 case 3: // hintp
1360 gen_op_movl_T0_env(offsetof(CPUSPARCState, hintp));
1361 break;
1362 case 5: // htba
1363 gen_op_movl_T0_env(offsetof(CPUSPARCState, htba));
1364 break;
1365 case 6: // hver
1366 gen_op_movl_T0_env(offsetof(CPUSPARCState, hver));
1367 break;
1368 case 31: // hstick_cmpr
1369 gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
1370 break;
1371 default:
1372 goto illegal_insn;
1373 }
1374#endif
e8af50a3
FB
1375 gen_movl_T0_reg(rd);
1376 break;
3475187d 1377 } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
0f8a249a
BS
1378 if (!supervisor(dc))
1379 goto priv_insn;
3475187d
FB
1380#ifdef TARGET_SPARC64
1381 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
1382 switch (rs1) {
1383 case 0: // tpc
1384 gen_op_rdtpc();
1385 break;
1386 case 1: // tnpc
1387 gen_op_rdtnpc();
1388 break;
1389 case 2: // tstate
1390 gen_op_rdtstate();
1391 break;
1392 case 3: // tt
1393 gen_op_rdtt();
1394 break;
1395 case 4: // tick
1396 gen_op_rdtick();
1397 break;
1398 case 5: // tba
1399 gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1400 break;
1401 case 6: // pstate
1402 gen_op_rdpstate();
1403 break;
1404 case 7: // tl
1405 gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
1406 break;
1407 case 8: // pil
1408 gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
1409 break;
1410 case 9: // cwp
1411 gen_op_rdcwp();
1412 break;
1413 case 10: // cansave
1414 gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
1415 break;
1416 case 11: // canrestore
1417 gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
1418 break;
1419 case 12: // cleanwin
1420 gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
1421 break;
1422 case 13: // otherwin
1423 gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
1424 break;
1425 case 14: // wstate
1426 gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
1427 break;
e9ebed4d
BS
1428 case 16: // UA2005 gl
1429 gen_op_movl_T0_env(offsetof(CPUSPARCState, gl));
1430 break;
1431 case 26: // UA2005 strand status
1432 if (!hypervisor(dc))
1433 goto priv_insn;
1434 gen_op_movl_T0_env(offsetof(CPUSPARCState, ssr));
1435 break;
0f8a249a
BS
1436 case 31: // ver
1437 gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
1438 break;
1439 case 15: // fq
1440 default:
1441 goto illegal_insn;
1442 }
3475187d 1443#else
0f8a249a 1444 gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
3475187d 1445#endif
e8af50a3
FB
1446 gen_movl_T0_reg(rd);
1447 break;
3475187d
FB
1448 } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
1449#ifdef TARGET_SPARC64
0f8a249a 1450 gen_op_flushw();
3475187d 1451#else
0f8a249a
BS
1452 if (!supervisor(dc))
1453 goto priv_insn;
1454 gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
e8af50a3 1455 gen_movl_T0_reg(rd);
3475187d 1456#endif
e8af50a3
FB
1457 break;
1458#endif
0f8a249a 1459 } else if (xop == 0x34) { /* FPU Operations */
a80dde08
FB
1460 if (gen_trap_ifnofpu(dc))
1461 goto jmp_insn;
0f8a249a 1462 gen_op_clear_ieee_excp_and_FTT();
e8af50a3 1463 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
1464 rs2 = GET_FIELD(insn, 27, 31);
1465 xop = GET_FIELD(insn, 18, 26);
1466 switch (xop) {
1467 case 0x1: /* fmovs */
1468 gen_op_load_fpr_FT0(rs2);
1469 gen_op_store_FT0_fpr(rd);
1470 break;
1471 case 0x5: /* fnegs */
1472 gen_op_load_fpr_FT1(rs2);
1473 gen_op_fnegs();
1474 gen_op_store_FT0_fpr(rd);
1475 break;
1476 case 0x9: /* fabss */
1477 gen_op_load_fpr_FT1(rs2);
1478 gen_op_fabss();
1479 gen_op_store_FT0_fpr(rd);
1480 break;
1481 case 0x29: /* fsqrts */
1482 gen_op_load_fpr_FT1(rs2);
1483 gen_op_fsqrts();
1484 gen_op_store_FT0_fpr(rd);
1485 break;
1486 case 0x2a: /* fsqrtd */
1487 gen_op_load_fpr_DT1(DFPREG(rs2));
1488 gen_op_fsqrtd();
1489 gen_op_store_DT0_fpr(DFPREG(rd));
1490 break;
1491 case 0x2b: /* fsqrtq */
1f587329
BS
1492#if defined(CONFIG_USER_ONLY)
1493 gen_op_load_fpr_QT1(QFPREG(rs2));
1494 gen_op_fsqrtq();
1495 gen_op_store_QT0_fpr(QFPREG(rd));
1496 break;
1497#else
0f8a249a 1498 goto nfpu_insn;
1f587329 1499#endif
0f8a249a
BS
1500 case 0x41:
1501 gen_op_load_fpr_FT0(rs1);
1502 gen_op_load_fpr_FT1(rs2);
1503 gen_op_fadds();
1504 gen_op_store_FT0_fpr(rd);
1505 break;
1506 case 0x42:
1507 gen_op_load_fpr_DT0(DFPREG(rs1));
1508 gen_op_load_fpr_DT1(DFPREG(rs2));
1509 gen_op_faddd();
1510 gen_op_store_DT0_fpr(DFPREG(rd));
1511 break;
1512 case 0x43: /* faddq */
1f587329
BS
1513#if defined(CONFIG_USER_ONLY)
1514 gen_op_load_fpr_QT0(QFPREG(rs1));
1515 gen_op_load_fpr_QT1(QFPREG(rs2));
1516 gen_op_faddq();
1517 gen_op_store_QT0_fpr(QFPREG(rd));
1518 break;
1519#else
0f8a249a 1520 goto nfpu_insn;
1f587329 1521#endif
0f8a249a
BS
1522 case 0x45:
1523 gen_op_load_fpr_FT0(rs1);
1524 gen_op_load_fpr_FT1(rs2);
1525 gen_op_fsubs();
1526 gen_op_store_FT0_fpr(rd);
1527 break;
1528 case 0x46:
1529 gen_op_load_fpr_DT0(DFPREG(rs1));
1530 gen_op_load_fpr_DT1(DFPREG(rs2));
1531 gen_op_fsubd();
1532 gen_op_store_DT0_fpr(DFPREG(rd));
1533 break;
1534 case 0x47: /* fsubq */
1f587329
BS
1535#if defined(CONFIG_USER_ONLY)
1536 gen_op_load_fpr_QT0(QFPREG(rs1));
1537 gen_op_load_fpr_QT1(QFPREG(rs2));
1538 gen_op_fsubq();
1539 gen_op_store_QT0_fpr(QFPREG(rd));
1540 break;
1541#else
0f8a249a 1542 goto nfpu_insn;
1f587329 1543#endif
0f8a249a
BS
1544 case 0x49:
1545 gen_op_load_fpr_FT0(rs1);
1546 gen_op_load_fpr_FT1(rs2);
1547 gen_op_fmuls();
1548 gen_op_store_FT0_fpr(rd);
1549 break;
1550 case 0x4a:
1551 gen_op_load_fpr_DT0(DFPREG(rs1));
1552 gen_op_load_fpr_DT1(DFPREG(rs2));
1553 gen_op_fmuld();
2382dc6b 1554 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1555 break;
1556 case 0x4b: /* fmulq */
1f587329
BS
1557#if defined(CONFIG_USER_ONLY)
1558 gen_op_load_fpr_QT0(QFPREG(rs1));
1559 gen_op_load_fpr_QT1(QFPREG(rs2));
1560 gen_op_fmulq();
1561 gen_op_store_QT0_fpr(QFPREG(rd));
1562 break;
1563#else
0f8a249a 1564 goto nfpu_insn;
1f587329 1565#endif
0f8a249a
BS
1566 case 0x4d:
1567 gen_op_load_fpr_FT0(rs1);
1568 gen_op_load_fpr_FT1(rs2);
1569 gen_op_fdivs();
1570 gen_op_store_FT0_fpr(rd);
1571 break;
1572 case 0x4e:
1573 gen_op_load_fpr_DT0(DFPREG(rs1));
1574 gen_op_load_fpr_DT1(DFPREG(rs2));
1575 gen_op_fdivd();
1576 gen_op_store_DT0_fpr(DFPREG(rd));
1577 break;
1578 case 0x4f: /* fdivq */
1f587329
BS
1579#if defined(CONFIG_USER_ONLY)
1580 gen_op_load_fpr_QT0(QFPREG(rs1));
1581 gen_op_load_fpr_QT1(QFPREG(rs2));
1582 gen_op_fdivq();
1583 gen_op_store_QT0_fpr(QFPREG(rd));
1584 break;
1585#else
0f8a249a 1586 goto nfpu_insn;
1f587329 1587#endif
0f8a249a
BS
1588 case 0x69:
1589 gen_op_load_fpr_FT0(rs1);
1590 gen_op_load_fpr_FT1(rs2);
1591 gen_op_fsmuld();
1592 gen_op_store_DT0_fpr(DFPREG(rd));
1593 break;
1594 case 0x6e: /* fdmulq */
1f587329
BS
1595#if defined(CONFIG_USER_ONLY)
1596 gen_op_load_fpr_DT0(DFPREG(rs1));
1597 gen_op_load_fpr_DT1(DFPREG(rs2));
1598 gen_op_fdmulq();
1599 gen_op_store_QT0_fpr(QFPREG(rd));
1600 break;
1601#else
0f8a249a 1602 goto nfpu_insn;
1f587329 1603#endif
0f8a249a
BS
1604 case 0xc4:
1605 gen_op_load_fpr_FT1(rs2);
1606 gen_op_fitos();
1607 gen_op_store_FT0_fpr(rd);
1608 break;
1609 case 0xc6:
1610 gen_op_load_fpr_DT1(DFPREG(rs2));
1611 gen_op_fdtos();
1612 gen_op_store_FT0_fpr(rd);
1613 break;
1614 case 0xc7: /* fqtos */
1f587329
BS
1615#if defined(CONFIG_USER_ONLY)
1616 gen_op_load_fpr_QT1(QFPREG(rs2));
1617 gen_op_fqtos();
1618 gen_op_store_FT0_fpr(rd);
1619 break;
1620#else
0f8a249a 1621 goto nfpu_insn;
1f587329 1622#endif
0f8a249a
BS
1623 case 0xc8:
1624 gen_op_load_fpr_FT1(rs2);
1625 gen_op_fitod();
1626 gen_op_store_DT0_fpr(DFPREG(rd));
1627 break;
1628 case 0xc9:
1629 gen_op_load_fpr_FT1(rs2);
1630 gen_op_fstod();
1631 gen_op_store_DT0_fpr(DFPREG(rd));
1632 break;
1633 case 0xcb: /* fqtod */
1f587329
BS
1634#if defined(CONFIG_USER_ONLY)
1635 gen_op_load_fpr_QT1(QFPREG(rs2));
1636 gen_op_fqtod();
1637 gen_op_store_DT0_fpr(DFPREG(rd));
1638 break;
1639#else
0f8a249a 1640 goto nfpu_insn;
1f587329 1641#endif
0f8a249a 1642 case 0xcc: /* fitoq */
1f587329
BS
1643#if defined(CONFIG_USER_ONLY)
1644 gen_op_load_fpr_FT1(rs2);
1645 gen_op_fitoq();
1646 gen_op_store_QT0_fpr(QFPREG(rd));
1647 break;
1648#else
0f8a249a 1649 goto nfpu_insn;
1f587329 1650#endif
0f8a249a 1651 case 0xcd: /* fstoq */
1f587329
BS
1652#if defined(CONFIG_USER_ONLY)
1653 gen_op_load_fpr_FT1(rs2);
1654 gen_op_fstoq();
1655 gen_op_store_QT0_fpr(QFPREG(rd));
1656 break;
1657#else
0f8a249a 1658 goto nfpu_insn;
1f587329 1659#endif
0f8a249a 1660 case 0xce: /* fdtoq */
1f587329
BS
1661#if defined(CONFIG_USER_ONLY)
1662 gen_op_load_fpr_DT1(DFPREG(rs2));
1663 gen_op_fdtoq();
1664 gen_op_store_QT0_fpr(QFPREG(rd));
1665 break;
1666#else
0f8a249a 1667 goto nfpu_insn;
1f587329 1668#endif
0f8a249a
BS
1669 case 0xd1:
1670 gen_op_load_fpr_FT1(rs2);
1671 gen_op_fstoi();
1672 gen_op_store_FT0_fpr(rd);
1673 break;
1674 case 0xd2:
2382dc6b 1675 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1676 gen_op_fdtoi();
1677 gen_op_store_FT0_fpr(rd);
1678 break;
1679 case 0xd3: /* fqtoi */
1f587329
BS
1680#if defined(CONFIG_USER_ONLY)
1681 gen_op_load_fpr_QT1(QFPREG(rs2));
1682 gen_op_fqtoi();
1683 gen_op_store_FT0_fpr(rd);
1684 break;
1685#else
0f8a249a 1686 goto nfpu_insn;
1f587329 1687#endif
3475187d 1688#ifdef TARGET_SPARC64
0f8a249a
BS
1689 case 0x2: /* V9 fmovd */
1690 gen_op_load_fpr_DT0(DFPREG(rs2));
1691 gen_op_store_DT0_fpr(DFPREG(rd));
1692 break;
1f587329
BS
1693 case 0x3: /* V9 fmovq */
1694#if defined(CONFIG_USER_ONLY)
1695 gen_op_load_fpr_QT0(QFPREG(rs2));
1696 gen_op_store_QT0_fpr(QFPREG(rd));
1697 break;
1698#else
1699 goto nfpu_insn;
1700#endif
0f8a249a
BS
1701 case 0x6: /* V9 fnegd */
1702 gen_op_load_fpr_DT1(DFPREG(rs2));
1703 gen_op_fnegd();
1704 gen_op_store_DT0_fpr(DFPREG(rd));
1705 break;
1f587329
BS
1706 case 0x7: /* V9 fnegq */
1707#if defined(CONFIG_USER_ONLY)
1708 gen_op_load_fpr_QT1(QFPREG(rs2));
1709 gen_op_fnegq();
1710 gen_op_store_QT0_fpr(QFPREG(rd));
1711 break;
1712#else
1713 goto nfpu_insn;
1714#endif
0f8a249a
BS
1715 case 0xa: /* V9 fabsd */
1716 gen_op_load_fpr_DT1(DFPREG(rs2));
1717 gen_op_fabsd();
1718 gen_op_store_DT0_fpr(DFPREG(rd));
1719 break;
1f587329
BS
1720 case 0xb: /* V9 fabsq */
1721#if defined(CONFIG_USER_ONLY)
1722 gen_op_load_fpr_QT1(QFPREG(rs2));
1723 gen_op_fabsq();
1724 gen_op_store_QT0_fpr(QFPREG(rd));
1725 break;
1726#else
1727 goto nfpu_insn;
1728#endif
0f8a249a
BS
1729 case 0x81: /* V9 fstox */
1730 gen_op_load_fpr_FT1(rs2);
1731 gen_op_fstox();
1732 gen_op_store_DT0_fpr(DFPREG(rd));
1733 break;
1734 case 0x82: /* V9 fdtox */
1735 gen_op_load_fpr_DT1(DFPREG(rs2));
1736 gen_op_fdtox();
1737 gen_op_store_DT0_fpr(DFPREG(rd));
1738 break;
1f587329
BS
1739 case 0x83: /* V9 fqtox */
1740#if defined(CONFIG_USER_ONLY)
1741 gen_op_load_fpr_QT1(QFPREG(rs2));
1742 gen_op_fqtox();
1743 gen_op_store_DT0_fpr(DFPREG(rd));
1744 break;
1745#else
1746 goto nfpu_insn;
1747#endif
0f8a249a
BS
1748 case 0x84: /* V9 fxtos */
1749 gen_op_load_fpr_DT1(DFPREG(rs2));
1750 gen_op_fxtos();
1751 gen_op_store_FT0_fpr(rd);
1752 break;
1753 case 0x88: /* V9 fxtod */
1754 gen_op_load_fpr_DT1(DFPREG(rs2));
1755 gen_op_fxtod();
1756 gen_op_store_DT0_fpr(DFPREG(rd));
1757 break;
0f8a249a 1758 case 0x8c: /* V9 fxtoq */
1f587329
BS
1759#if defined(CONFIG_USER_ONLY)
1760 gen_op_load_fpr_DT1(DFPREG(rs2));
1761 gen_op_fxtoq();
1762 gen_op_store_QT0_fpr(QFPREG(rd));
1763 break;
1764#else
0f8a249a 1765 goto nfpu_insn;
1f587329 1766#endif
0f8a249a
BS
1767#endif
1768 default:
1769 goto illegal_insn;
1770 }
1771 } else if (xop == 0x35) { /* FPU Operations */
3475187d 1772#ifdef TARGET_SPARC64
0f8a249a 1773 int cond;
3475187d 1774#endif
a80dde08
FB
1775 if (gen_trap_ifnofpu(dc))
1776 goto jmp_insn;
0f8a249a 1777 gen_op_clear_ieee_excp_and_FTT();
cf495bcf 1778 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
1779 rs2 = GET_FIELD(insn, 27, 31);
1780 xop = GET_FIELD(insn, 18, 26);
3475187d 1781#ifdef TARGET_SPARC64
0f8a249a
BS
1782 if ((xop & 0x11f) == 0x005) { // V9 fmovsr
1783 cond = GET_FIELD_SP(insn, 14, 17);
1784 gen_op_load_fpr_FT0(rd);
1785 gen_op_load_fpr_FT1(rs2);
1786 rs1 = GET_FIELD(insn, 13, 17);
1787 gen_movl_reg_T0(rs1);
1788 flush_T2(dc);
1789 gen_cond_reg(cond);
1790 gen_op_fmovs_cc();
1791 gen_op_store_FT0_fpr(rd);
1792 break;
1793 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
1794 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1795 gen_op_load_fpr_DT0(DFPREG(rd));
1796 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1797 flush_T2(dc);
1798 rs1 = GET_FIELD(insn, 13, 17);
1799 gen_movl_reg_T0(rs1);
1800 gen_cond_reg(cond);
1801 gen_op_fmovs_cc();
2382dc6b 1802 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1803 break;
1804 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
1f587329
BS
1805#if defined(CONFIG_USER_ONLY)
1806 cond = GET_FIELD_SP(insn, 14, 17);
1807 gen_op_load_fpr_QT0(QFPREG(rd));
1808 gen_op_load_fpr_QT1(QFPREG(rs2));
1809 flush_T2(dc);
1810 rs1 = GET_FIELD(insn, 13, 17);
1811 gen_movl_reg_T0(rs1);
1812 gen_cond_reg(cond);
1813 gen_op_fmovq_cc();
1814 gen_op_store_QT0_fpr(QFPREG(rd));
1815 break;
1816#else
0f8a249a 1817 goto nfpu_insn;
1f587329 1818#endif
0f8a249a
BS
1819 }
1820#endif
1821 switch (xop) {
3475187d 1822#ifdef TARGET_SPARC64
0f8a249a
BS
1823 case 0x001: /* V9 fmovscc %fcc0 */
1824 cond = GET_FIELD_SP(insn, 14, 17);
1825 gen_op_load_fpr_FT0(rd);
1826 gen_op_load_fpr_FT1(rs2);
1827 flush_T2(dc);
1828 gen_fcond[0][cond]();
1829 gen_op_fmovs_cc();
1830 gen_op_store_FT0_fpr(rd);
1831 break;
1832 case 0x002: /* V9 fmovdcc %fcc0 */
1833 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1834 gen_op_load_fpr_DT0(DFPREG(rd));
1835 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1836 flush_T2(dc);
1837 gen_fcond[0][cond]();
1838 gen_op_fmovd_cc();
2382dc6b 1839 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1840 break;
1841 case 0x003: /* V9 fmovqcc %fcc0 */
1f587329
BS
1842#if defined(CONFIG_USER_ONLY)
1843 cond = GET_FIELD_SP(insn, 14, 17);
1844 gen_op_load_fpr_QT0(QFPREG(rd));
1845 gen_op_load_fpr_QT1(QFPREG(rs2));
1846 flush_T2(dc);
1847 gen_fcond[0][cond]();
1848 gen_op_fmovq_cc();
1849 gen_op_store_QT0_fpr(QFPREG(rd));
1850 break;
1851#else
0f8a249a 1852 goto nfpu_insn;
1f587329 1853#endif
0f8a249a
BS
1854 case 0x041: /* V9 fmovscc %fcc1 */
1855 cond = GET_FIELD_SP(insn, 14, 17);
1856 gen_op_load_fpr_FT0(rd);
1857 gen_op_load_fpr_FT1(rs2);
1858 flush_T2(dc);
1859 gen_fcond[1][cond]();
1860 gen_op_fmovs_cc();
1861 gen_op_store_FT0_fpr(rd);
1862 break;
1863 case 0x042: /* V9 fmovdcc %fcc1 */
1864 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1865 gen_op_load_fpr_DT0(DFPREG(rd));
1866 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1867 flush_T2(dc);
1868 gen_fcond[1][cond]();
1869 gen_op_fmovd_cc();
2382dc6b 1870 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1871 break;
1872 case 0x043: /* V9 fmovqcc %fcc1 */
1f587329
BS
1873#if defined(CONFIG_USER_ONLY)
1874 cond = GET_FIELD_SP(insn, 14, 17);
1875 gen_op_load_fpr_QT0(QFPREG(rd));
1876 gen_op_load_fpr_QT1(QFPREG(rs2));
1877 flush_T2(dc);
1878 gen_fcond[1][cond]();
1879 gen_op_fmovq_cc();
1880 gen_op_store_QT0_fpr(QFPREG(rd));
1881 break;
1882#else
0f8a249a 1883 goto nfpu_insn;
1f587329 1884#endif
0f8a249a
BS
1885 case 0x081: /* V9 fmovscc %fcc2 */
1886 cond = GET_FIELD_SP(insn, 14, 17);
1887 gen_op_load_fpr_FT0(rd);
1888 gen_op_load_fpr_FT1(rs2);
1889 flush_T2(dc);
1890 gen_fcond[2][cond]();
1891 gen_op_fmovs_cc();
1892 gen_op_store_FT0_fpr(rd);
1893 break;
1894 case 0x082: /* V9 fmovdcc %fcc2 */
1895 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1896 gen_op_load_fpr_DT0(DFPREG(rd));
1897 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1898 flush_T2(dc);
1899 gen_fcond[2][cond]();
1900 gen_op_fmovd_cc();
2382dc6b 1901 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1902 break;
1903 case 0x083: /* V9 fmovqcc %fcc2 */
1f587329
BS
1904#if defined(CONFIG_USER_ONLY)
1905 cond = GET_FIELD_SP(insn, 14, 17);
1906 gen_op_load_fpr_QT0(rd);
1907 gen_op_load_fpr_QT1(rs2);
1908 flush_T2(dc);
1909 gen_fcond[2][cond]();
1910 gen_op_fmovq_cc();
1911 gen_op_store_QT0_fpr(rd);
1912 break;
1913#else
0f8a249a 1914 goto nfpu_insn;
1f587329 1915#endif
0f8a249a
BS
1916 case 0x0c1: /* V9 fmovscc %fcc3 */
1917 cond = GET_FIELD_SP(insn, 14, 17);
1918 gen_op_load_fpr_FT0(rd);
1919 gen_op_load_fpr_FT1(rs2);
1920 flush_T2(dc);
1921 gen_fcond[3][cond]();
1922 gen_op_fmovs_cc();
1923 gen_op_store_FT0_fpr(rd);
1924 break;
1925 case 0x0c2: /* V9 fmovdcc %fcc3 */
1926 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1927 gen_op_load_fpr_DT0(DFPREG(rd));
1928 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1929 flush_T2(dc);
1930 gen_fcond[3][cond]();
1931 gen_op_fmovd_cc();
2382dc6b 1932 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1933 break;
1934 case 0x0c3: /* V9 fmovqcc %fcc3 */
1f587329
BS
1935#if defined(CONFIG_USER_ONLY)
1936 cond = GET_FIELD_SP(insn, 14, 17);
1937 gen_op_load_fpr_QT0(QFPREG(rd));
1938 gen_op_load_fpr_QT1(QFPREG(rs2));
1939 flush_T2(dc);
1940 gen_fcond[3][cond]();
1941 gen_op_fmovq_cc();
1942 gen_op_store_QT0_fpr(QFPREG(rd));
1943 break;
1944#else
0f8a249a 1945 goto nfpu_insn;
1f587329 1946#endif
0f8a249a
BS
1947 case 0x101: /* V9 fmovscc %icc */
1948 cond = GET_FIELD_SP(insn, 14, 17);
1949 gen_op_load_fpr_FT0(rd);
1950 gen_op_load_fpr_FT1(rs2);
1951 flush_T2(dc);
1952 gen_cond[0][cond]();
1953 gen_op_fmovs_cc();
1954 gen_op_store_FT0_fpr(rd);
1955 break;
1956 case 0x102: /* V9 fmovdcc %icc */
1957 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1958 gen_op_load_fpr_DT0(DFPREG(rd));
1959 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1960 flush_T2(dc);
1961 gen_cond[0][cond]();
1962 gen_op_fmovd_cc();
2382dc6b 1963 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1964 break;
1965 case 0x103: /* V9 fmovqcc %icc */
1f587329
BS
1966#if defined(CONFIG_USER_ONLY)
1967 cond = GET_FIELD_SP(insn, 14, 17);
1968 gen_op_load_fpr_QT0(rd);
1969 gen_op_load_fpr_QT1(rs2);
1970 flush_T2(dc);
1971 gen_cond[0][cond]();
1972 gen_op_fmovq_cc();
1973 gen_op_store_QT0_fpr(rd);
1974 break;
1975#else
0f8a249a 1976 goto nfpu_insn;
1f587329 1977#endif
0f8a249a
BS
1978 case 0x181: /* V9 fmovscc %xcc */
1979 cond = GET_FIELD_SP(insn, 14, 17);
1980 gen_op_load_fpr_FT0(rd);
1981 gen_op_load_fpr_FT1(rs2);
1982 flush_T2(dc);
1983 gen_cond[1][cond]();
1984 gen_op_fmovs_cc();
1985 gen_op_store_FT0_fpr(rd);
1986 break;
1987 case 0x182: /* V9 fmovdcc %xcc */
1988 cond = GET_FIELD_SP(insn, 14, 17);
2382dc6b
BS
1989 gen_op_load_fpr_DT0(DFPREG(rd));
1990 gen_op_load_fpr_DT1(DFPREG(rs2));
0f8a249a
BS
1991 flush_T2(dc);
1992 gen_cond[1][cond]();
1993 gen_op_fmovd_cc();
2382dc6b 1994 gen_op_store_DT0_fpr(DFPREG(rd));
0f8a249a
BS
1995 break;
1996 case 0x183: /* V9 fmovqcc %xcc */
1f587329
BS
1997#if defined(CONFIG_USER_ONLY)
1998 cond = GET_FIELD_SP(insn, 14, 17);
1999 gen_op_load_fpr_QT0(rd);
2000 gen_op_load_fpr_QT1(rs2);
2001 flush_T2(dc);
2002 gen_cond[1][cond]();
2003 gen_op_fmovq_cc();
2004 gen_op_store_QT0_fpr(rd);
2005 break;
2006#else
0f8a249a
BS
2007 goto nfpu_insn;
2008#endif
1f587329
BS
2009#endif
2010 case 0x51: /* fcmps, V9 %fcc */
0f8a249a
BS
2011 gen_op_load_fpr_FT0(rs1);
2012 gen_op_load_fpr_FT1(rs2);
3475187d 2013#ifdef TARGET_SPARC64
0f8a249a 2014 gen_fcmps[rd & 3]();
3475187d 2015#else
0f8a249a 2016 gen_op_fcmps();
3475187d 2017#endif
0f8a249a 2018 break;
1f587329 2019 case 0x52: /* fcmpd, V9 %fcc */
0f8a249a
BS
2020 gen_op_load_fpr_DT0(DFPREG(rs1));
2021 gen_op_load_fpr_DT1(DFPREG(rs2));
3475187d 2022#ifdef TARGET_SPARC64
0f8a249a 2023 gen_fcmpd[rd & 3]();
3475187d 2024#else
0f8a249a
BS
2025 gen_op_fcmpd();
2026#endif
2027 break;
1f587329
BS
2028 case 0x53: /* fcmpq, V9 %fcc */
2029#if defined(CONFIG_USER_ONLY)
2030 gen_op_load_fpr_QT0(QFPREG(rs1));
2031 gen_op_load_fpr_QT1(QFPREG(rs2));
2032#ifdef TARGET_SPARC64
2033 gen_fcmpq[rd & 3]();
2034#else
2035 gen_op_fcmpq();
2036#endif
2037 break;
2038#else /* !defined(CONFIG_USER_ONLY) */
0f8a249a 2039 goto nfpu_insn;
1f587329 2040#endif
0f8a249a
BS
2041 case 0x55: /* fcmpes, V9 %fcc */
2042 gen_op_load_fpr_FT0(rs1);
2043 gen_op_load_fpr_FT1(rs2);
3475187d 2044#ifdef TARGET_SPARC64
0f8a249a 2045 gen_fcmpes[rd & 3]();
3475187d 2046#else
0f8a249a 2047 gen_op_fcmpes();
3475187d 2048#endif
0f8a249a
BS
2049 break;
2050 case 0x56: /* fcmped, V9 %fcc */
2051 gen_op_load_fpr_DT0(DFPREG(rs1));
2052 gen_op_load_fpr_DT1(DFPREG(rs2));
3475187d 2053#ifdef TARGET_SPARC64
0f8a249a 2054 gen_fcmped[rd & 3]();
3475187d 2055#else
0f8a249a
BS
2056 gen_op_fcmped();
2057#endif
2058 break;
1f587329
BS
2059 case 0x57: /* fcmpeq, V9 %fcc */
2060#if defined(CONFIG_USER_ONLY)
2061 gen_op_load_fpr_QT0(QFPREG(rs1));
2062 gen_op_load_fpr_QT1(QFPREG(rs2));
2063#ifdef TARGET_SPARC64
2064 gen_fcmpeq[rd & 3]();
2065#else
2066 gen_op_fcmpeq();
2067#endif
2068 break;
2069#else/* !defined(CONFIG_USER_ONLY) */
0f8a249a 2070 goto nfpu_insn;
1f587329 2071#endif
0f8a249a
BS
2072 default:
2073 goto illegal_insn;
2074 }
e80cfcfc 2075#if defined(OPTIM)
0f8a249a
BS
2076 } else if (xop == 0x2) {
2077 // clr/mov shortcut
e80cfcfc
FB
2078
2079 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2080 if (rs1 == 0) {
2081 // or %g0, x, y -> mov T1, x; mov y, T1
2082 if (IS_IMM) { /* immediate */
2083 rs2 = GET_FIELDs(insn, 19, 31);
2084 gen_movl_simm_T1(rs2);
2085 } else { /* register */
2086 rs2 = GET_FIELD(insn, 27, 31);
2087 gen_movl_reg_T1(rs2);
2088 }
2089 gen_movl_T1_reg(rd);
2090 } else {
2091 gen_movl_reg_T0(rs1);
2092 if (IS_IMM) { /* immediate */
2093 // or x, #0, y -> mov T1, x; mov y, T1
2094 rs2 = GET_FIELDs(insn, 19, 31);
2095 if (rs2 != 0) {
2096 gen_movl_simm_T1(rs2);
2097 gen_op_or_T1_T0();
2098 }
2099 } else { /* register */
2100 // or x, %g0, y -> mov T1, x; mov y, T1
2101 rs2 = GET_FIELD(insn, 27, 31);
2102 if (rs2 != 0) {
2103 gen_movl_reg_T1(rs2);
2104 gen_op_or_T1_T0();
2105 }
2106 }
2107 gen_movl_T0_reg(rd);
2108 }
83469015
FB
2109#endif
2110#ifdef TARGET_SPARC64
0f8a249a 2111 } else if (xop == 0x25) { /* sll, V9 sllx */
83469015 2112 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2113 gen_movl_reg_T0(rs1);
2114 if (IS_IMM) { /* immediate */
83469015
FB
2115 rs2 = GET_FIELDs(insn, 20, 31);
2116 gen_movl_simm_T1(rs2);
0f8a249a 2117 } else { /* register */
83469015
FB
2118 rs2 = GET_FIELD(insn, 27, 31);
2119 gen_movl_reg_T1(rs2);
2120 }
0f8a249a
BS
2121 if (insn & (1 << 12))
2122 gen_op_sllx();
2123 else
2124 gen_op_sll();
2125 gen_movl_T0_reg(rd);
2126 } else if (xop == 0x26) { /* srl, V9 srlx */
83469015 2127 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2128 gen_movl_reg_T0(rs1);
2129 if (IS_IMM) { /* immediate */
83469015
FB
2130 rs2 = GET_FIELDs(insn, 20, 31);
2131 gen_movl_simm_T1(rs2);
0f8a249a 2132 } else { /* register */
83469015
FB
2133 rs2 = GET_FIELD(insn, 27, 31);
2134 gen_movl_reg_T1(rs2);
2135 }
0f8a249a
BS
2136 if (insn & (1 << 12))
2137 gen_op_srlx();
2138 else
2139 gen_op_srl();
2140 gen_movl_T0_reg(rd);
2141 } else if (xop == 0x27) { /* sra, V9 srax */
83469015 2142 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2143 gen_movl_reg_T0(rs1);
2144 if (IS_IMM) { /* immediate */
83469015
FB
2145 rs2 = GET_FIELDs(insn, 20, 31);
2146 gen_movl_simm_T1(rs2);
0f8a249a 2147 } else { /* register */
83469015
FB
2148 rs2 = GET_FIELD(insn, 27, 31);
2149 gen_movl_reg_T1(rs2);
2150 }
0f8a249a
BS
2151 if (insn & (1 << 12))
2152 gen_op_srax();
2153 else
2154 gen_op_sra();
2155 gen_movl_T0_reg(rd);
e80cfcfc 2156#endif
fcc72045 2157 } else if (xop < 0x36) {
e80cfcfc 2158 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2159 gen_movl_reg_T0(rs1);
2160 if (IS_IMM) { /* immediate */
cf495bcf 2161 rs2 = GET_FIELDs(insn, 19, 31);
3475187d 2162 gen_movl_simm_T1(rs2);
0f8a249a 2163 } else { /* register */
cf495bcf
FB
2164 rs2 = GET_FIELD(insn, 27, 31);
2165 gen_movl_reg_T1(rs2);
2166 }
2167 if (xop < 0x20) {
2168 switch (xop & ~0x10) {
2169 case 0x0:
2170 if (xop & 0x10)
2171 gen_op_add_T1_T0_cc();
2172 else
2173 gen_op_add_T1_T0();
2174 break;
2175 case 0x1:
2176 gen_op_and_T1_T0();
2177 if (xop & 0x10)
2178 gen_op_logic_T0_cc();
2179 break;
2180 case 0x2:
0f8a249a
BS
2181 gen_op_or_T1_T0();
2182 if (xop & 0x10)
2183 gen_op_logic_T0_cc();
2184 break;
cf495bcf
FB
2185 case 0x3:
2186 gen_op_xor_T1_T0();
2187 if (xop & 0x10)
2188 gen_op_logic_T0_cc();
2189 break;
2190 case 0x4:
2191 if (xop & 0x10)
2192 gen_op_sub_T1_T0_cc();
2193 else
2194 gen_op_sub_T1_T0();
2195 break;
2196 case 0x5:
2197 gen_op_andn_T1_T0();
2198 if (xop & 0x10)
2199 gen_op_logic_T0_cc();
2200 break;
2201 case 0x6:
2202 gen_op_orn_T1_T0();
2203 if (xop & 0x10)
2204 gen_op_logic_T0_cc();
2205 break;
2206 case 0x7:
2207 gen_op_xnor_T1_T0();
2208 if (xop & 0x10)
2209 gen_op_logic_T0_cc();
2210 break;
2211 case 0x8:
cf495bcf 2212 if (xop & 0x10)
af7bf89b
FB
2213 gen_op_addx_T1_T0_cc();
2214 else
2215 gen_op_addx_T1_T0();
cf495bcf 2216 break;
ded3ab80 2217#ifdef TARGET_SPARC64
0f8a249a 2218 case 0x9: /* V9 mulx */
ded3ab80
PB
2219 gen_op_mulx_T1_T0();
2220 break;
2221#endif
cf495bcf
FB
2222 case 0xa:
2223 gen_op_umul_T1_T0();
2224 if (xop & 0x10)
2225 gen_op_logic_T0_cc();
2226 break;
2227 case 0xb:
2228 gen_op_smul_T1_T0();
2229 if (xop & 0x10)
2230 gen_op_logic_T0_cc();
2231 break;
2232 case 0xc:
cf495bcf 2233 if (xop & 0x10)
af7bf89b
FB
2234 gen_op_subx_T1_T0_cc();
2235 else
2236 gen_op_subx_T1_T0();
cf495bcf 2237 break;
ded3ab80 2238#ifdef TARGET_SPARC64
0f8a249a 2239 case 0xd: /* V9 udivx */
ded3ab80
PB
2240 gen_op_udivx_T1_T0();
2241 break;
2242#endif
cf495bcf
FB
2243 case 0xe:
2244 gen_op_udiv_T1_T0();
2245 if (xop & 0x10)
2246 gen_op_div_cc();
2247 break;
2248 case 0xf:
2249 gen_op_sdiv_T1_T0();
2250 if (xop & 0x10)
2251 gen_op_div_cc();
2252 break;
2253 default:
2254 goto illegal_insn;
2255 }
0f8a249a 2256 gen_movl_T0_reg(rd);
cf495bcf
FB
2257 } else {
2258 switch (xop) {
0f8a249a
BS
2259 case 0x20: /* taddcc */
2260 gen_op_tadd_T1_T0_cc();
2261 gen_movl_T0_reg(rd);
2262 break;
2263 case 0x21: /* tsubcc */
2264 gen_op_tsub_T1_T0_cc();
2265 gen_movl_T0_reg(rd);
2266 break;
2267 case 0x22: /* taddcctv */
90251fb9 2268 save_state(dc);
0f8a249a
BS
2269 gen_op_tadd_T1_T0_ccTV();
2270 gen_movl_T0_reg(rd);
2271 break;
2272 case 0x23: /* tsubcctv */
90251fb9 2273 save_state(dc);
0f8a249a
BS
2274 gen_op_tsub_T1_T0_ccTV();
2275 gen_movl_T0_reg(rd);
2276 break;
cf495bcf
FB
2277 case 0x24: /* mulscc */
2278 gen_op_mulscc_T1_T0();
2279 gen_movl_T0_reg(rd);
2280 break;
83469015 2281#ifndef TARGET_SPARC64
0f8a249a
BS
2282 case 0x25: /* sll */
2283 gen_op_sll();
cf495bcf
FB
2284 gen_movl_T0_reg(rd);
2285 break;
83469015 2286 case 0x26: /* srl */
0f8a249a 2287 gen_op_srl();
cf495bcf
FB
2288 gen_movl_T0_reg(rd);
2289 break;
83469015 2290 case 0x27: /* sra */
0f8a249a 2291 gen_op_sra();
cf495bcf
FB
2292 gen_movl_T0_reg(rd);
2293 break;
83469015 2294#endif
cf495bcf
FB
2295 case 0x30:
2296 {
cf495bcf 2297 switch(rd) {
3475187d 2298 case 0: /* wry */
0f8a249a
BS
2299 gen_op_xor_T1_T0();
2300 gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
cf495bcf 2301 break;
65fe7b09
BS
2302#ifndef TARGET_SPARC64
2303 case 0x01 ... 0x0f: /* undefined in the
2304 SPARCv8 manual, nop
2305 on the microSPARC
2306 II */
2307 case 0x10 ... 0x1f: /* implementation-dependent
2308 in the SPARCv8
2309 manual, nop on the
2310 microSPARC II */
2311 break;
2312#else
0f8a249a 2313 case 0x2: /* V9 wrccr */
ee0b03fd 2314 gen_op_xor_T1_T0();
3475187d 2315 gen_op_wrccr();
0f8a249a
BS
2316 break;
2317 case 0x3: /* V9 wrasi */
ee0b03fd 2318 gen_op_xor_T1_T0();
0f8a249a
BS
2319 gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
2320 break;
2321 case 0x6: /* V9 wrfprs */
2322 gen_op_xor_T1_T0();
2323 gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
3299908c
BS
2324 save_state(dc);
2325 gen_op_next_insn();
57fec1fe 2326 tcg_gen_exit_tb(0);
3299908c 2327 dc->is_br = 1;
0f8a249a
BS
2328 break;
2329 case 0xf: /* V9 sir, nop if user */
3475187d 2330#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
2331 if (supervisor(dc))
2332 gen_op_sir();
3475187d 2333#endif
0f8a249a
BS
2334 break;
2335 case 0x13: /* Graphics Status */
725cb90b
FB
2336 if (gen_trap_ifnofpu(dc))
2337 goto jmp_insn;
ee0b03fd 2338 gen_op_xor_T1_T0();
0f8a249a
BS
2339 gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
2340 break;
2341 case 0x17: /* Tick compare */
83469015 2342#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
2343 if (!supervisor(dc))
2344 goto illegal_insn;
83469015 2345#endif
ee0b03fd 2346 gen_op_xor_T1_T0();
20c9f095
BS
2347 gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
2348 gen_op_wrtick_cmpr();
0f8a249a
BS
2349 break;
2350 case 0x18: /* System tick */
83469015 2351#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
2352 if (!supervisor(dc))
2353 goto illegal_insn;
83469015 2354#endif
ee0b03fd 2355 gen_op_xor_T1_T0();
20c9f095 2356 gen_op_wrstick();
0f8a249a
BS
2357 break;
2358 case 0x19: /* System tick compare */
83469015 2359#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
2360 if (!supervisor(dc))
2361 goto illegal_insn;
3475187d 2362#endif
ee0b03fd 2363 gen_op_xor_T1_T0();
20c9f095
BS
2364 gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
2365 gen_op_wrstick_cmpr();
0f8a249a 2366 break;
83469015 2367
0f8a249a
BS
2368 case 0x10: /* Performance Control */
2369 case 0x11: /* Performance Instrumentation Counter */
2370 case 0x12: /* Dispatch Control */
2371 case 0x14: /* Softint set */
2372 case 0x15: /* Softint clear */
2373 case 0x16: /* Softint write */
83469015 2374#endif
3475187d 2375 default:
cf495bcf
FB
2376 goto illegal_insn;
2377 }
2378 }
2379 break;
e8af50a3 2380#if !defined(CONFIG_USER_ONLY)
af7bf89b 2381 case 0x31: /* wrpsr, V9 saved, restored */
e8af50a3 2382 {
0f8a249a
BS
2383 if (!supervisor(dc))
2384 goto priv_insn;
3475187d 2385#ifdef TARGET_SPARC64
0f8a249a
BS
2386 switch (rd) {
2387 case 0:
2388 gen_op_saved();
2389 break;
2390 case 1:
2391 gen_op_restored();
2392 break;
e9ebed4d
BS
2393 case 2: /* UA2005 allclean */
2394 case 3: /* UA2005 otherw */
2395 case 4: /* UA2005 normalw */
2396 case 5: /* UA2005 invalw */
2397 // XXX
0f8a249a 2398 default:
3475187d
FB
2399 goto illegal_insn;
2400 }
2401#else
e8af50a3
FB
2402 gen_op_xor_T1_T0();
2403 gen_op_wrpsr();
9e61bde5
FB
2404 save_state(dc);
2405 gen_op_next_insn();
57fec1fe 2406 tcg_gen_exit_tb(0);
0f8a249a 2407 dc->is_br = 1;
3475187d 2408#endif
e8af50a3
FB
2409 }
2410 break;
af7bf89b 2411 case 0x32: /* wrwim, V9 wrpr */
e8af50a3 2412 {
0f8a249a
BS
2413 if (!supervisor(dc))
2414 goto priv_insn;
e8af50a3 2415 gen_op_xor_T1_T0();
3475187d 2416#ifdef TARGET_SPARC64
0f8a249a
BS
2417 switch (rd) {
2418 case 0: // tpc
2419 gen_op_wrtpc();
2420 break;
2421 case 1: // tnpc
2422 gen_op_wrtnpc();
2423 break;
2424 case 2: // tstate
2425 gen_op_wrtstate();
2426 break;
2427 case 3: // tt
2428 gen_op_wrtt();
2429 break;
2430 case 4: // tick
2431 gen_op_wrtick();
2432 break;
2433 case 5: // tba
2434 gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
2435 break;
2436 case 6: // pstate
2437 gen_op_wrpstate();
ded3ab80
PB
2438 save_state(dc);
2439 gen_op_next_insn();
57fec1fe 2440 tcg_gen_exit_tb(0);
ded3ab80 2441 dc->is_br = 1;
0f8a249a
BS
2442 break;
2443 case 7: // tl
2444 gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
2445 break;
2446 case 8: // pil
2447 gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
2448 break;
2449 case 9: // cwp
2450 gen_op_wrcwp();
2451 break;
2452 case 10: // cansave
2453 gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
2454 break;
2455 case 11: // canrestore
2456 gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
2457 break;
2458 case 12: // cleanwin
2459 gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
2460 break;
2461 case 13: // otherwin
2462 gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
2463 break;
2464 case 14: // wstate
2465 gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
2466 break;
e9ebed4d
BS
2467 case 16: // UA2005 gl
2468 gen_op_movl_env_T0(offsetof(CPUSPARCState, gl));
2469 break;
2470 case 26: // UA2005 strand status
2471 if (!hypervisor(dc))
2472 goto priv_insn;
2473 gen_op_movl_env_T0(offsetof(CPUSPARCState, ssr));
2474 break;
0f8a249a
BS
2475 default:
2476 goto illegal_insn;
2477 }
3475187d 2478#else
0f8a249a 2479 gen_op_wrwim();
3475187d 2480#endif
e8af50a3
FB
2481 }
2482 break;
e9ebed4d 2483 case 0x33: /* wrtbr, UA2005 wrhpr */
e8af50a3 2484 {
e9ebed4d 2485#ifndef TARGET_SPARC64
0f8a249a
BS
2486 if (!supervisor(dc))
2487 goto priv_insn;
e8af50a3 2488 gen_op_xor_T1_T0();
e9ebed4d
BS
2489 gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
2490#else
2491 if (!hypervisor(dc))
2492 goto priv_insn;
2493 gen_op_xor_T1_T0();
2494 switch (rd) {
2495 case 0: // hpstate
2496 // XXX gen_op_wrhpstate();
2497 save_state(dc);
2498 gen_op_next_insn();
57fec1fe 2499 tcg_gen_exit_tb(0);
e9ebed4d
BS
2500 dc->is_br = 1;
2501 break;
2502 case 1: // htstate
2503 // XXX gen_op_wrhtstate();
2504 break;
2505 case 3: // hintp
2506 gen_op_movl_env_T0(offsetof(CPUSPARCState, hintp));
2507 break;
2508 case 5: // htba
2509 gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
2510 break;
2511 case 31: // hstick_cmpr
20c9f095
BS
2512 gen_op_movtl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
2513 gen_op_wrhstick_cmpr();
e9ebed4d
BS
2514 break;
2515 case 6: // hver readonly
2516 default:
2517 goto illegal_insn;
2518 }
2519#endif
e8af50a3
FB
2520 }
2521 break;
2522#endif
3475187d 2523#ifdef TARGET_SPARC64
0f8a249a
BS
2524 case 0x2c: /* V9 movcc */
2525 {
2526 int cc = GET_FIELD_SP(insn, 11, 12);
2527 int cond = GET_FIELD_SP(insn, 14, 17);
2528 if (IS_IMM) { /* immediate */
2529 rs2 = GET_FIELD_SPs(insn, 0, 10);
2530 gen_movl_simm_T1(rs2);
2531 }
2532 else {
2533 rs2 = GET_FIELD_SP(insn, 0, 4);
2534 gen_movl_reg_T1(rs2);
2535 }
2536 gen_movl_reg_T0(rd);
2537 flush_T2(dc);
2538 if (insn & (1 << 18)) {
2539 if (cc == 0)
2540 gen_cond[0][cond]();
2541 else if (cc == 2)
2542 gen_cond[1][cond]();
2543 else
2544 goto illegal_insn;
2545 } else {
2546 gen_fcond[cc][cond]();
2547 }
2548 gen_op_mov_cc();
2549 gen_movl_T0_reg(rd);
2550 break;
2551 }
2552 case 0x2d: /* V9 sdivx */
3475187d 2553 gen_op_sdivx_T1_T0();
0f8a249a
BS
2554 gen_movl_T0_reg(rd);
2555 break;
2556 case 0x2e: /* V9 popc */
2557 {
2558 if (IS_IMM) { /* immediate */
2559 rs2 = GET_FIELD_SPs(insn, 0, 12);
2560 gen_movl_simm_T1(rs2);
2561 // XXX optimize: popc(constant)
2562 }
2563 else {
2564 rs2 = GET_FIELD_SP(insn, 0, 4);
2565 gen_movl_reg_T1(rs2);
2566 }
2567 gen_op_popc();
2568 gen_movl_T0_reg(rd);
2569 }
2570 case 0x2f: /* V9 movr */
2571 {
2572 int cond = GET_FIELD_SP(insn, 10, 12);
2573 rs1 = GET_FIELD(insn, 13, 17);
2574 flush_T2(dc);
2575 gen_movl_reg_T0(rs1);
2576 gen_cond_reg(cond);
2577 if (IS_IMM) { /* immediate */
2578 rs2 = GET_FIELD_SPs(insn, 0, 9);
2579 gen_movl_simm_T1(rs2);
2580 }
2581 else {
2582 rs2 = GET_FIELD_SP(insn, 0, 4);
2583 gen_movl_reg_T1(rs2);
2584 }
2585 gen_movl_reg_T0(rd);
2586 gen_op_mov_cc();
2587 gen_movl_T0_reg(rd);
2588 break;
2589 }
2590#endif
2591 default:
2592 goto illegal_insn;
2593 }
2594 }
3299908c
BS
2595 } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
2596#ifdef TARGET_SPARC64
2597 int opf = GET_FIELD_SP(insn, 5, 13);
2598 rs1 = GET_FIELD(insn, 13, 17);
2599 rs2 = GET_FIELD(insn, 27, 31);
e9ebed4d
BS
2600 if (gen_trap_ifnofpu(dc))
2601 goto jmp_insn;
3299908c
BS
2602
2603 switch (opf) {
e9ebed4d
BS
2604 case 0x000: /* VIS I edge8cc */
2605 case 0x001: /* VIS II edge8n */
2606 case 0x002: /* VIS I edge8lcc */
2607 case 0x003: /* VIS II edge8ln */
2608 case 0x004: /* VIS I edge16cc */
2609 case 0x005: /* VIS II edge16n */
2610 case 0x006: /* VIS I edge16lcc */
2611 case 0x007: /* VIS II edge16ln */
2612 case 0x008: /* VIS I edge32cc */
2613 case 0x009: /* VIS II edge32n */
2614 case 0x00a: /* VIS I edge32lcc */
2615 case 0x00b: /* VIS II edge32ln */
2616 // XXX
2617 goto illegal_insn;
2618 case 0x010: /* VIS I array8 */
2619 gen_movl_reg_T0(rs1);
2620 gen_movl_reg_T1(rs2);
2621 gen_op_array8();
2622 gen_movl_T0_reg(rd);
2623 break;
2624 case 0x012: /* VIS I array16 */
2625 gen_movl_reg_T0(rs1);
2626 gen_movl_reg_T1(rs2);
2627 gen_op_array16();
2628 gen_movl_T0_reg(rd);
2629 break;
2630 case 0x014: /* VIS I array32 */
2631 gen_movl_reg_T0(rs1);
2632 gen_movl_reg_T1(rs2);
2633 gen_op_array32();
2634 gen_movl_T0_reg(rd);
2635 break;
3299908c 2636 case 0x018: /* VIS I alignaddr */
3299908c
BS
2637 gen_movl_reg_T0(rs1);
2638 gen_movl_reg_T1(rs2);
2639 gen_op_alignaddr();
2640 gen_movl_T0_reg(rd);
2641 break;
e9ebed4d 2642 case 0x019: /* VIS II bmask */
3299908c 2643 case 0x01a: /* VIS I alignaddrl */
3299908c 2644 // XXX
e9ebed4d
BS
2645 goto illegal_insn;
2646 case 0x020: /* VIS I fcmple16 */
2382dc6b
BS
2647 gen_op_load_fpr_DT0(DFPREG(rs1));
2648 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2649 gen_op_fcmple16();
2382dc6b 2650 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2651 break;
2652 case 0x022: /* VIS I fcmpne16 */
2382dc6b
BS
2653 gen_op_load_fpr_DT0(DFPREG(rs1));
2654 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2655 gen_op_fcmpne16();
2382dc6b 2656 gen_op_store_DT0_fpr(DFPREG(rd));
3299908c 2657 break;
e9ebed4d 2658 case 0x024: /* VIS I fcmple32 */
2382dc6b
BS
2659 gen_op_load_fpr_DT0(DFPREG(rs1));
2660 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2661 gen_op_fcmple32();
2382dc6b 2662 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2663 break;
2664 case 0x026: /* VIS I fcmpne32 */
2382dc6b
BS
2665 gen_op_load_fpr_DT0(DFPREG(rs1));
2666 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2667 gen_op_fcmpne32();
2382dc6b 2668 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2669 break;
2670 case 0x028: /* VIS I fcmpgt16 */
2382dc6b
BS
2671 gen_op_load_fpr_DT0(DFPREG(rs1));
2672 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2673 gen_op_fcmpgt16();
2382dc6b 2674 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2675 break;
2676 case 0x02a: /* VIS I fcmpeq16 */
2382dc6b
BS
2677 gen_op_load_fpr_DT0(DFPREG(rs1));
2678 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2679 gen_op_fcmpeq16();
2382dc6b 2680 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2681 break;
2682 case 0x02c: /* VIS I fcmpgt32 */
2382dc6b
BS
2683 gen_op_load_fpr_DT0(DFPREG(rs1));
2684 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2685 gen_op_fcmpgt32();
2382dc6b 2686 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2687 break;
2688 case 0x02e: /* VIS I fcmpeq32 */
2382dc6b
BS
2689 gen_op_load_fpr_DT0(DFPREG(rs1));
2690 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2691 gen_op_fcmpeq32();
2382dc6b 2692 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2693 break;
2694 case 0x031: /* VIS I fmul8x16 */
2382dc6b
BS
2695 gen_op_load_fpr_DT0(DFPREG(rs1));
2696 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2697 gen_op_fmul8x16();
2382dc6b 2698 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2699 break;
2700 case 0x033: /* VIS I fmul8x16au */
2382dc6b
BS
2701 gen_op_load_fpr_DT0(DFPREG(rs1));
2702 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2703 gen_op_fmul8x16au();
2382dc6b 2704 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2705 break;
2706 case 0x035: /* VIS I fmul8x16al */
2382dc6b
BS
2707 gen_op_load_fpr_DT0(DFPREG(rs1));
2708 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2709 gen_op_fmul8x16al();
2382dc6b 2710 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2711 break;
2712 case 0x036: /* VIS I fmul8sux16 */
2382dc6b
BS
2713 gen_op_load_fpr_DT0(DFPREG(rs1));
2714 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2715 gen_op_fmul8sux16();
2382dc6b 2716 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2717 break;
2718 case 0x037: /* VIS I fmul8ulx16 */
2382dc6b
BS
2719 gen_op_load_fpr_DT0(DFPREG(rs1));
2720 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2721 gen_op_fmul8ulx16();
2382dc6b 2722 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2723 break;
2724 case 0x038: /* VIS I fmuld8sux16 */
2382dc6b
BS
2725 gen_op_load_fpr_DT0(DFPREG(rs1));
2726 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2727 gen_op_fmuld8sux16();
2382dc6b 2728 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2729 break;
2730 case 0x039: /* VIS I fmuld8ulx16 */
2382dc6b
BS
2731 gen_op_load_fpr_DT0(DFPREG(rs1));
2732 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2733 gen_op_fmuld8ulx16();
2382dc6b 2734 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2735 break;
2736 case 0x03a: /* VIS I fpack32 */
2737 case 0x03b: /* VIS I fpack16 */
2738 case 0x03d: /* VIS I fpackfix */
2739 case 0x03e: /* VIS I pdist */
2740 // XXX
2741 goto illegal_insn;
3299908c 2742 case 0x048: /* VIS I faligndata */
2382dc6b
BS
2743 gen_op_load_fpr_DT0(DFPREG(rs1));
2744 gen_op_load_fpr_DT1(DFPREG(rs2));
3299908c 2745 gen_op_faligndata();
2382dc6b 2746 gen_op_store_DT0_fpr(DFPREG(rd));
3299908c 2747 break;
e9ebed4d 2748 case 0x04b: /* VIS I fpmerge */
2382dc6b
BS
2749 gen_op_load_fpr_DT0(DFPREG(rs1));
2750 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2751 gen_op_fpmerge();
2382dc6b 2752 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2753 break;
2754 case 0x04c: /* VIS II bshuffle */
2755 // XXX
2756 goto illegal_insn;
2757 case 0x04d: /* VIS I fexpand */
2382dc6b
BS
2758 gen_op_load_fpr_DT0(DFPREG(rs1));
2759 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2760 gen_op_fexpand();
2382dc6b 2761 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2762 break;
2763 case 0x050: /* VIS I fpadd16 */
2382dc6b
BS
2764 gen_op_load_fpr_DT0(DFPREG(rs1));
2765 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2766 gen_op_fpadd16();
2382dc6b 2767 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2768 break;
2769 case 0x051: /* VIS I fpadd16s */
2770 gen_op_load_fpr_FT0(rs1);
2771 gen_op_load_fpr_FT1(rs2);
2772 gen_op_fpadd16s();
2773 gen_op_store_FT0_fpr(rd);
2774 break;
2775 case 0x052: /* VIS I fpadd32 */
2382dc6b
BS
2776 gen_op_load_fpr_DT0(DFPREG(rs1));
2777 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2778 gen_op_fpadd32();
2382dc6b 2779 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2780 break;
2781 case 0x053: /* VIS I fpadd32s */
2782 gen_op_load_fpr_FT0(rs1);
2783 gen_op_load_fpr_FT1(rs2);
2784 gen_op_fpadd32s();
2785 gen_op_store_FT0_fpr(rd);
2786 break;
2787 case 0x054: /* VIS I fpsub16 */
2382dc6b
BS
2788 gen_op_load_fpr_DT0(DFPREG(rs1));
2789 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2790 gen_op_fpsub16();
2382dc6b 2791 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2792 break;
2793 case 0x055: /* VIS I fpsub16s */
2794 gen_op_load_fpr_FT0(rs1);
2795 gen_op_load_fpr_FT1(rs2);
2796 gen_op_fpsub16s();
2797 gen_op_store_FT0_fpr(rd);
2798 break;
2799 case 0x056: /* VIS I fpsub32 */
2382dc6b
BS
2800 gen_op_load_fpr_DT0(DFPREG(rs1));
2801 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2802 gen_op_fpadd32();
2382dc6b 2803 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2804 break;
2805 case 0x057: /* VIS I fpsub32s */
2806 gen_op_load_fpr_FT0(rs1);
2807 gen_op_load_fpr_FT1(rs2);
2808 gen_op_fpsub32s();
2809 gen_op_store_FT0_fpr(rd);
2810 break;
3299908c 2811 case 0x060: /* VIS I fzero */
3299908c 2812 gen_op_movl_DT0_0();
2382dc6b 2813 gen_op_store_DT0_fpr(DFPREG(rd));
3299908c
BS
2814 break;
2815 case 0x061: /* VIS I fzeros */
3299908c
BS
2816 gen_op_movl_FT0_0();
2817 gen_op_store_FT0_fpr(rd);
2818 break;
e9ebed4d 2819 case 0x062: /* VIS I fnor */
2382dc6b
BS
2820 gen_op_load_fpr_DT0(DFPREG(rs1));
2821 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2822 gen_op_fnor();
2382dc6b 2823 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2824 break;
2825 case 0x063: /* VIS I fnors */
2826 gen_op_load_fpr_FT0(rs1);
2827 gen_op_load_fpr_FT1(rs2);
2828 gen_op_fnors();
2829 gen_op_store_FT0_fpr(rd);
2830 break;
2831 case 0x064: /* VIS I fandnot2 */
2382dc6b
BS
2832 gen_op_load_fpr_DT1(DFPREG(rs1));
2833 gen_op_load_fpr_DT0(DFPREG(rs2));
e9ebed4d 2834 gen_op_fandnot();
2382dc6b 2835 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2836 break;
2837 case 0x065: /* VIS I fandnot2s */
2838 gen_op_load_fpr_FT1(rs1);
2839 gen_op_load_fpr_FT0(rs2);
2840 gen_op_fandnots();
2841 gen_op_store_FT0_fpr(rd);
2842 break;
2843 case 0x066: /* VIS I fnot2 */
2382dc6b 2844 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2845 gen_op_fnot();
2382dc6b 2846 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2847 break;
2848 case 0x067: /* VIS I fnot2s */
2849 gen_op_load_fpr_FT1(rs2);
2850 gen_op_fnot();
2851 gen_op_store_FT0_fpr(rd);
2852 break;
2853 case 0x068: /* VIS I fandnot1 */
2382dc6b
BS
2854 gen_op_load_fpr_DT0(DFPREG(rs1));
2855 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2856 gen_op_fandnot();
2382dc6b 2857 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2858 break;
2859 case 0x069: /* VIS I fandnot1s */
2860 gen_op_load_fpr_FT0(rs1);
2861 gen_op_load_fpr_FT1(rs2);
2862 gen_op_fandnots();
2863 gen_op_store_FT0_fpr(rd);
2864 break;
2865 case 0x06a: /* VIS I fnot1 */
2382dc6b 2866 gen_op_load_fpr_DT1(DFPREG(rs1));
e9ebed4d 2867 gen_op_fnot();
2382dc6b 2868 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2869 break;
2870 case 0x06b: /* VIS I fnot1s */
2871 gen_op_load_fpr_FT1(rs1);
2872 gen_op_fnot();
2873 gen_op_store_FT0_fpr(rd);
2874 break;
2875 case 0x06c: /* VIS I fxor */
2382dc6b
BS
2876 gen_op_load_fpr_DT0(DFPREG(rs1));
2877 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2878 gen_op_fxor();
2382dc6b 2879 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2880 break;
2881 case 0x06d: /* VIS I fxors */
2882 gen_op_load_fpr_FT0(rs1);
2883 gen_op_load_fpr_FT1(rs2);
2884 gen_op_fxors();
2885 gen_op_store_FT0_fpr(rd);
2886 break;
2887 case 0x06e: /* VIS I fnand */
2382dc6b
BS
2888 gen_op_load_fpr_DT0(DFPREG(rs1));
2889 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2890 gen_op_fnand();
2382dc6b 2891 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2892 break;
2893 case 0x06f: /* VIS I fnands */
2894 gen_op_load_fpr_FT0(rs1);
2895 gen_op_load_fpr_FT1(rs2);
2896 gen_op_fnands();
2897 gen_op_store_FT0_fpr(rd);
2898 break;
2899 case 0x070: /* VIS I fand */
2382dc6b
BS
2900 gen_op_load_fpr_DT0(DFPREG(rs1));
2901 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2902 gen_op_fand();
2382dc6b 2903 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2904 break;
2905 case 0x071: /* VIS I fands */
2906 gen_op_load_fpr_FT0(rs1);
2907 gen_op_load_fpr_FT1(rs2);
2908 gen_op_fands();
2909 gen_op_store_FT0_fpr(rd);
2910 break;
2911 case 0x072: /* VIS I fxnor */
2382dc6b
BS
2912 gen_op_load_fpr_DT0(DFPREG(rs1));
2913 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2914 gen_op_fxnor();
2382dc6b 2915 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2916 break;
2917 case 0x073: /* VIS I fxnors */
2918 gen_op_load_fpr_FT0(rs1);
2919 gen_op_load_fpr_FT1(rs2);
2920 gen_op_fxnors();
2921 gen_op_store_FT0_fpr(rd);
2922 break;
3299908c 2923 case 0x074: /* VIS I fsrc1 */
2382dc6b
BS
2924 gen_op_load_fpr_DT0(DFPREG(rs1));
2925 gen_op_store_DT0_fpr(DFPREG(rd));
3299908c
BS
2926 break;
2927 case 0x075: /* VIS I fsrc1s */
3299908c
BS
2928 gen_op_load_fpr_FT0(rs1);
2929 gen_op_store_FT0_fpr(rd);
2930 break;
e9ebed4d 2931 case 0x076: /* VIS I fornot2 */
2382dc6b
BS
2932 gen_op_load_fpr_DT1(DFPREG(rs1));
2933 gen_op_load_fpr_DT0(DFPREG(rs2));
e9ebed4d 2934 gen_op_fornot();
2382dc6b 2935 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2936 break;
2937 case 0x077: /* VIS I fornot2s */
2938 gen_op_load_fpr_FT1(rs1);
2939 gen_op_load_fpr_FT0(rs2);
2940 gen_op_fornots();
2941 gen_op_store_FT0_fpr(rd);
2942 break;
3299908c 2943 case 0x078: /* VIS I fsrc2 */
2382dc6b
BS
2944 gen_op_load_fpr_DT0(DFPREG(rs2));
2945 gen_op_store_DT0_fpr(DFPREG(rd));
3299908c
BS
2946 break;
2947 case 0x079: /* VIS I fsrc2s */
3299908c
BS
2948 gen_op_load_fpr_FT0(rs2);
2949 gen_op_store_FT0_fpr(rd);
2950 break;
e9ebed4d 2951 case 0x07a: /* VIS I fornot1 */
2382dc6b
BS
2952 gen_op_load_fpr_DT0(DFPREG(rs1));
2953 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2954 gen_op_fornot();
2382dc6b 2955 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2956 break;
2957 case 0x07b: /* VIS I fornot1s */
2958 gen_op_load_fpr_FT0(rs1);
2959 gen_op_load_fpr_FT1(rs2);
2960 gen_op_fornots();
2961 gen_op_store_FT0_fpr(rd);
2962 break;
2963 case 0x07c: /* VIS I for */
2382dc6b
BS
2964 gen_op_load_fpr_DT0(DFPREG(rs1));
2965 gen_op_load_fpr_DT1(DFPREG(rs2));
e9ebed4d 2966 gen_op_for();
2382dc6b 2967 gen_op_store_DT0_fpr(DFPREG(rd));
e9ebed4d
BS
2968 break;
2969 case 0x07d: /* VIS I fors */
2970 gen_op_load_fpr_FT0(rs1);
2971 gen_op_load_fpr_FT1(rs2);
2972 gen_op_fors();
2973 gen_op_store_FT0_fpr(rd);
2974 break;
3299908c 2975 case 0x07e: /* VIS I fone */
3299908c 2976 gen_op_movl_DT0_1();
2382dc6b 2977 gen_op_store_DT0_fpr(DFPREG(rd));
3299908c
BS
2978 break;
2979 case 0x07f: /* VIS I fones */
3299908c
BS
2980 gen_op_movl_FT0_1();
2981 gen_op_store_FT0_fpr(rd);
2982 break;
e9ebed4d
BS
2983 case 0x080: /* VIS I shutdown */
2984 case 0x081: /* VIS II siam */
2985 // XXX
2986 goto illegal_insn;
3299908c
BS
2987 default:
2988 goto illegal_insn;
2989 }
2990#else
0f8a249a 2991 goto ncp_insn;
3299908c
BS
2992#endif
2993 } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
fcc72045 2994#ifdef TARGET_SPARC64
0f8a249a 2995 goto illegal_insn;
fcc72045 2996#else
0f8a249a 2997 goto ncp_insn;
fcc72045 2998#endif
3475187d 2999#ifdef TARGET_SPARC64
0f8a249a 3000 } else if (xop == 0x39) { /* V9 return */
3475187d 3001 rs1 = GET_FIELD(insn, 13, 17);
1ad21e69 3002 save_state(dc);
0f8a249a
BS
3003 gen_movl_reg_T0(rs1);
3004 if (IS_IMM) { /* immediate */
3005 rs2 = GET_FIELDs(insn, 19, 31);
3475187d 3006#if defined(OPTIM)
0f8a249a 3007 if (rs2) {
3475187d 3008#endif
0f8a249a
BS
3009 gen_movl_simm_T1(rs2);
3010 gen_op_add_T1_T0();
3475187d 3011#if defined(OPTIM)
0f8a249a 3012 }
3475187d 3013#endif
0f8a249a 3014 } else { /* register */
3475187d
FB
3015 rs2 = GET_FIELD(insn, 27, 31);
3016#if defined(OPTIM)
0f8a249a 3017 if (rs2) {
3475187d 3018#endif
0f8a249a
BS
3019 gen_movl_reg_T1(rs2);
3020 gen_op_add_T1_T0();
3475187d 3021#if defined(OPTIM)
0f8a249a 3022 }
3475187d
FB
3023#endif
3024 }
0f8a249a
BS
3025 gen_op_restore();
3026 gen_mov_pc_npc(dc);
6ea4a6c8 3027 gen_op_check_align_T0_3();
0f8a249a
BS
3028 gen_op_movl_npc_T0();
3029 dc->npc = DYNAMIC_PC;
3030 goto jmp_insn;
3475187d 3031#endif
0f8a249a 3032 } else {
e80cfcfc 3033 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
3034 gen_movl_reg_T0(rs1);
3035 if (IS_IMM) { /* immediate */
3036 rs2 = GET_FIELDs(insn, 19, 31);
e80cfcfc 3037#if defined(OPTIM)
0f8a249a 3038 if (rs2) {
e8af50a3 3039#endif
0f8a249a
BS
3040 gen_movl_simm_T1(rs2);
3041 gen_op_add_T1_T0();
e80cfcfc 3042#if defined(OPTIM)
0f8a249a 3043 }
e8af50a3 3044#endif
0f8a249a 3045 } else { /* register */
e80cfcfc
FB
3046 rs2 = GET_FIELD(insn, 27, 31);
3047#if defined(OPTIM)
0f8a249a 3048 if (rs2) {
e80cfcfc 3049#endif
0f8a249a
BS
3050 gen_movl_reg_T1(rs2);
3051 gen_op_add_T1_T0();
e80cfcfc 3052#if defined(OPTIM)
0f8a249a 3053 }
e8af50a3 3054#endif
cf495bcf 3055 }
0f8a249a
BS
3056 switch (xop) {
3057 case 0x38: /* jmpl */
3058 {
3059 if (rd != 0) {
ded3ab80
PB
3060#ifdef TARGET_SPARC64
3061 if (dc->pc == (uint32_t)dc->pc) {
3062 gen_op_movl_T1_im(dc->pc);
3063 } else {
3064 gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
3065 }
3066#else
0f8a249a 3067 gen_op_movl_T1_im(dc->pc);
ded3ab80 3068#endif
0f8a249a
BS
3069 gen_movl_T1_reg(rd);
3070 }
0bee699e 3071 gen_mov_pc_npc(dc);
6ea4a6c8 3072 gen_op_check_align_T0_3();
0f8a249a
BS
3073 gen_op_movl_npc_T0();
3074 dc->npc = DYNAMIC_PC;
3075 }
3076 goto jmp_insn;
3475187d 3077#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
0f8a249a
BS
3078 case 0x39: /* rett, V9 return */
3079 {
3080 if (!supervisor(dc))
3081 goto priv_insn;
0bee699e 3082 gen_mov_pc_npc(dc);
6ea4a6c8 3083 gen_op_check_align_T0_3();
0f8a249a
BS
3084 gen_op_movl_npc_T0();
3085 dc->npc = DYNAMIC_PC;
3086 gen_op_rett();
3087 }
3088 goto jmp_insn;
3089#endif
3090 case 0x3b: /* flush */
3091 gen_op_flush_T0();
3092 break;
3093 case 0x3c: /* save */
3094 save_state(dc);
3095 gen_op_save();
3096 gen_movl_T0_reg(rd);
3097 break;
3098 case 0x3d: /* restore */
3099 save_state(dc);
3100 gen_op_restore();
3101 gen_movl_T0_reg(rd);
3102 break;
3475187d 3103#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
0f8a249a
BS
3104 case 0x3e: /* V9 done/retry */
3105 {
3106 switch (rd) {
3107 case 0:
3108 if (!supervisor(dc))
3109 goto priv_insn;
3110 dc->npc = DYNAMIC_PC;
3111 dc->pc = DYNAMIC_PC;
3112 gen_op_done();
3113 goto jmp_insn;
3114 case 1:
3115 if (!supervisor(dc))
3116 goto priv_insn;
3117 dc->npc = DYNAMIC_PC;
3118 dc->pc = DYNAMIC_PC;
3119 gen_op_retry();
3120 goto jmp_insn;
3121 default:
3122 goto illegal_insn;
3123 }
3124 }
3125 break;
3126#endif
3127 default:
3128 goto illegal_insn;
3129 }
cf495bcf 3130 }
0f8a249a
BS
3131 break;
3132 }
3133 break;
3134 case 3: /* load/store instructions */
3135 {
3136 unsigned int xop = GET_FIELD(insn, 7, 12);
3137 rs1 = GET_FIELD(insn, 13, 17);
2371aaa2 3138 save_state(dc);
0f8a249a 3139 gen_movl_reg_T0(rs1);
81ad8ba2
BS
3140 if (xop == 0x3c || xop == 0x3e)
3141 {
3142 rs2 = GET_FIELD(insn, 27, 31);
3143 gen_movl_reg_T1(rs2);
3144 }
3145 else if (IS_IMM) { /* immediate */
0f8a249a 3146 rs2 = GET_FIELDs(insn, 19, 31);
e80cfcfc 3147#if defined(OPTIM)
0f8a249a 3148 if (rs2 != 0) {
e80cfcfc 3149#endif
0f8a249a
BS
3150 gen_movl_simm_T1(rs2);
3151 gen_op_add_T1_T0();
e80cfcfc 3152#if defined(OPTIM)
0f8a249a 3153 }
e80cfcfc 3154#endif
0f8a249a
BS
3155 } else { /* register */
3156 rs2 = GET_FIELD(insn, 27, 31);
e80cfcfc 3157#if defined(OPTIM)
0f8a249a 3158 if (rs2 != 0) {
e80cfcfc 3159#endif
0f8a249a
BS
3160 gen_movl_reg_T1(rs2);
3161 gen_op_add_T1_T0();
e80cfcfc 3162#if defined(OPTIM)
0f8a249a 3163 }
e80cfcfc 3164#endif
0f8a249a 3165 }
2f2ecb83
BS
3166 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
3167 (xop > 0x17 && xop <= 0x1d ) ||
3168 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
0f8a249a
BS
3169 switch (xop) {
3170 case 0x0: /* load word */
6ea4a6c8 3171 gen_op_check_align_T0_3();
dc011987 3172#ifndef TARGET_SPARC64
0f8a249a 3173 gen_op_ldst(ld);
dc011987
BS
3174#else
3175 gen_op_ldst(lduw);
3176#endif
0f8a249a
BS
3177 break;
3178 case 0x1: /* load unsigned byte */
3179 gen_op_ldst(ldub);
3180 break;
3181 case 0x2: /* load unsigned halfword */
6ea4a6c8 3182 gen_op_check_align_T0_1();
0f8a249a
BS
3183 gen_op_ldst(lduh);
3184 break;
3185 case 0x3: /* load double word */
0f8a249a 3186 if (rd & 1)
d4218d99 3187 goto illegal_insn;
8f577d3d 3188 gen_op_check_align_T0_7();
0f8a249a
BS
3189 gen_op_ldst(ldd);
3190 gen_movl_T0_reg(rd + 1);
3191 break;
3192 case 0x9: /* load signed byte */
3193 gen_op_ldst(ldsb);
3194 break;
3195 case 0xa: /* load signed halfword */
6ea4a6c8 3196 gen_op_check_align_T0_1();
0f8a249a
BS
3197 gen_op_ldst(ldsh);
3198 break;
3199 case 0xd: /* ldstub -- XXX: should be atomically */
3200 gen_op_ldst(ldstub);
3201 break;
3202 case 0x0f: /* swap register with memory. Also atomically */
6ea4a6c8 3203 gen_op_check_align_T0_3();
0f8a249a
BS
3204 gen_movl_reg_T1(rd);
3205 gen_op_ldst(swap);
3206 break;
3475187d 3207#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 3208 case 0x10: /* load word alternate */
3475187d 3209#ifndef TARGET_SPARC64
0f8a249a
BS
3210 if (IS_IMM)
3211 goto illegal_insn;
3212 if (!supervisor(dc))
3213 goto priv_insn;
6ea4a6c8 3214#endif
8f577d3d 3215 gen_op_check_align_T0_3();
81ad8ba2 3216 gen_ld_asi(insn, 4, 0);
0f8a249a
BS
3217 break;
3218 case 0x11: /* load unsigned byte alternate */
3475187d 3219#ifndef TARGET_SPARC64
0f8a249a
BS
3220 if (IS_IMM)
3221 goto illegal_insn;
3222 if (!supervisor(dc))
3223 goto priv_insn;
3224#endif
81ad8ba2 3225 gen_ld_asi(insn, 1, 0);
0f8a249a
BS
3226 break;
3227 case 0x12: /* load unsigned halfword alternate */
3475187d 3228#ifndef TARGET_SPARC64
0f8a249a
BS
3229 if (IS_IMM)
3230 goto illegal_insn;
3231 if (!supervisor(dc))
3232 goto priv_insn;
3475187d 3233#endif
8f577d3d 3234 gen_op_check_align_T0_1();
81ad8ba2 3235 gen_ld_asi(insn, 2, 0);
0f8a249a
BS
3236 break;
3237 case 0x13: /* load double word alternate */
3475187d 3238#ifndef TARGET_SPARC64
0f8a249a
BS
3239 if (IS_IMM)
3240 goto illegal_insn;
3241 if (!supervisor(dc))
3242 goto priv_insn;
3475187d 3243#endif
0f8a249a 3244 if (rd & 1)
d4218d99 3245 goto illegal_insn;
6ea4a6c8 3246 gen_op_check_align_T0_7();
81ad8ba2 3247 gen_ldda_asi(insn);
0f8a249a
BS
3248 gen_movl_T0_reg(rd + 1);
3249 break;
3250 case 0x19: /* load signed byte alternate */
3475187d 3251#ifndef TARGET_SPARC64
0f8a249a
BS
3252 if (IS_IMM)
3253 goto illegal_insn;
3254 if (!supervisor(dc))
3255 goto priv_insn;
3256#endif
81ad8ba2 3257 gen_ld_asi(insn, 1, 1);
0f8a249a
BS
3258 break;
3259 case 0x1a: /* load signed halfword alternate */
3475187d 3260#ifndef TARGET_SPARC64
0f8a249a
BS
3261 if (IS_IMM)
3262 goto illegal_insn;
3263 if (!supervisor(dc))
3264 goto priv_insn;
3475187d 3265#endif
8f577d3d 3266 gen_op_check_align_T0_1();
81ad8ba2 3267 gen_ld_asi(insn, 2, 1);
0f8a249a
BS
3268 break;
3269 case 0x1d: /* ldstuba -- XXX: should be atomically */
3475187d 3270#ifndef TARGET_SPARC64
0f8a249a
BS
3271 if (IS_IMM)
3272 goto illegal_insn;
3273 if (!supervisor(dc))
3274 goto priv_insn;
3275#endif
81ad8ba2 3276 gen_ldstub_asi(insn);
0f8a249a
BS
3277 break;
3278 case 0x1f: /* swap reg with alt. memory. Also atomically */
3475187d 3279#ifndef TARGET_SPARC64
0f8a249a
BS
3280 if (IS_IMM)
3281 goto illegal_insn;
3282 if (!supervisor(dc))
3283 goto priv_insn;
6ea4a6c8 3284#endif
8f577d3d 3285 gen_op_check_align_T0_3();
81ad8ba2
BS
3286 gen_movl_reg_T1(rd);
3287 gen_swap_asi(insn);
0f8a249a 3288 break;
3475187d
FB
3289
3290#ifndef TARGET_SPARC64
0f8a249a
BS
3291 case 0x30: /* ldc */
3292 case 0x31: /* ldcsr */
3293 case 0x33: /* lddc */
3294 goto ncp_insn;
3475187d
FB
3295#endif
3296#endif
3297#ifdef TARGET_SPARC64
0f8a249a 3298 case 0x08: /* V9 ldsw */
6ea4a6c8 3299 gen_op_check_align_T0_3();
0f8a249a
BS
3300 gen_op_ldst(ldsw);
3301 break;
3302 case 0x0b: /* V9 ldx */
6ea4a6c8 3303 gen_op_check_align_T0_7();
0f8a249a
BS
3304 gen_op_ldst(ldx);
3305 break;
3306 case 0x18: /* V9 ldswa */
6ea4a6c8 3307 gen_op_check_align_T0_3();
81ad8ba2 3308 gen_ld_asi(insn, 4, 1);
0f8a249a
BS
3309 break;
3310 case 0x1b: /* V9 ldxa */
6ea4a6c8 3311 gen_op_check_align_T0_7();
81ad8ba2 3312 gen_ld_asi(insn, 8, 0);
0f8a249a
BS
3313 break;
3314 case 0x2d: /* V9 prefetch, no effect */
3315 goto skip_move;
3316 case 0x30: /* V9 ldfa */
6ea4a6c8 3317 gen_op_check_align_T0_3();
2382dc6b 3318 gen_ldf_asi(insn, 4, rd);
81ad8ba2 3319 goto skip_move;
0f8a249a 3320 case 0x33: /* V9 lddfa */
3391c818 3321 gen_op_check_align_T0_3();
2382dc6b 3322 gen_ldf_asi(insn, 8, DFPREG(rd));
81ad8ba2 3323 goto skip_move;
0f8a249a
BS
3324 case 0x3d: /* V9 prefetcha, no effect */
3325 goto skip_move;
3326 case 0x32: /* V9 ldqfa */
1f587329
BS
3327#if defined(CONFIG_USER_ONLY)
3328 gen_op_check_align_T0_3();
2382dc6b 3329 gen_ldf_asi(insn, 16, QFPREG(rd));
1f587329
BS
3330 goto skip_move;
3331#else
0f8a249a 3332 goto nfpu_insn;
1f587329 3333#endif
0f8a249a
BS
3334#endif
3335 default:
3336 goto illegal_insn;
3337 }
3338 gen_movl_T1_reg(rd);
3475187d 3339#ifdef TARGET_SPARC64
0f8a249a 3340 skip_move: ;
3475187d 3341#endif
0f8a249a 3342 } else if (xop >= 0x20 && xop < 0x24) {
a80dde08
FB
3343 if (gen_trap_ifnofpu(dc))
3344 goto jmp_insn;
0f8a249a
BS
3345 switch (xop) {
3346 case 0x20: /* load fpreg */
6ea4a6c8 3347 gen_op_check_align_T0_3();
0f8a249a
BS
3348 gen_op_ldst(ldf);
3349 gen_op_store_FT0_fpr(rd);
3350 break;
3351 case 0x21: /* load fsr */
6ea4a6c8 3352 gen_op_check_align_T0_3();
0f8a249a
BS
3353 gen_op_ldst(ldf);
3354 gen_op_ldfsr();
3355 break;
3356 case 0x22: /* load quad fpreg */
1f587329
BS
3357#if defined(CONFIG_USER_ONLY)
3358 gen_op_check_align_T0_7();
3359 gen_op_ldst(ldqf);
3360 gen_op_store_QT0_fpr(QFPREG(rd));
3361 break;
3362#else
0f8a249a 3363 goto nfpu_insn;
1f587329 3364#endif
0f8a249a 3365 case 0x23: /* load double fpreg */
6ea4a6c8 3366 gen_op_check_align_T0_7();
0f8a249a
BS
3367 gen_op_ldst(lddf);
3368 gen_op_store_DT0_fpr(DFPREG(rd));
3369 break;
3370 default:
3371 goto illegal_insn;
3372 }
3373 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
3374 xop == 0xe || xop == 0x1e) {
3375 gen_movl_reg_T1(rd);
3376 switch (xop) {
3377 case 0x4:
6ea4a6c8 3378 gen_op_check_align_T0_3();
0f8a249a
BS
3379 gen_op_ldst(st);
3380 break;
3381 case 0x5:
3382 gen_op_ldst(stb);
3383 break;
3384 case 0x6:
6ea4a6c8 3385 gen_op_check_align_T0_1();
0f8a249a
BS
3386 gen_op_ldst(sth);
3387 break;
3388 case 0x7:
3389 if (rd & 1)
d4218d99 3390 goto illegal_insn;
6ea4a6c8 3391 gen_op_check_align_T0_7();
72cbca10 3392 flush_T2(dc);
0f8a249a
BS
3393 gen_movl_reg_T2(rd + 1);
3394 gen_op_ldst(std);
3395 break;
3475187d 3396#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 3397 case 0x14:
3475187d 3398#ifndef TARGET_SPARC64
0f8a249a
BS
3399 if (IS_IMM)
3400 goto illegal_insn;
3401 if (!supervisor(dc))
3402 goto priv_insn;
6ea4a6c8 3403#endif
6ea4a6c8 3404 gen_op_check_align_T0_3();
81ad8ba2 3405 gen_st_asi(insn, 4);
d39c0b99 3406 break;
0f8a249a 3407 case 0x15:
3475187d 3408#ifndef TARGET_SPARC64
0f8a249a
BS
3409 if (IS_IMM)
3410 goto illegal_insn;
3411 if (!supervisor(dc))
3412 goto priv_insn;
3475187d 3413#endif
81ad8ba2 3414 gen_st_asi(insn, 1);
d39c0b99 3415 break;
0f8a249a 3416 case 0x16:
3475187d 3417#ifndef TARGET_SPARC64
0f8a249a
BS
3418 if (IS_IMM)
3419 goto illegal_insn;
3420 if (!supervisor(dc))
3421 goto priv_insn;
6ea4a6c8 3422#endif
6ea4a6c8 3423 gen_op_check_align_T0_1();
81ad8ba2 3424 gen_st_asi(insn, 2);
d39c0b99 3425 break;
0f8a249a 3426 case 0x17:
3475187d 3427#ifndef TARGET_SPARC64
0f8a249a
BS
3428 if (IS_IMM)
3429 goto illegal_insn;
3430 if (!supervisor(dc))
3431 goto priv_insn;
3475187d 3432#endif
0f8a249a 3433 if (rd & 1)
d4218d99 3434 goto illegal_insn;
6ea4a6c8 3435 gen_op_check_align_T0_7();
e8af50a3 3436 flush_T2(dc);
0f8a249a 3437 gen_movl_reg_T2(rd + 1);
81ad8ba2 3438 gen_stda_asi(insn);
d39c0b99 3439 break;
e80cfcfc 3440#endif
3475187d 3441#ifdef TARGET_SPARC64
0f8a249a 3442 case 0x0e: /* V9 stx */
6ea4a6c8 3443 gen_op_check_align_T0_7();
0f8a249a
BS
3444 gen_op_ldst(stx);
3445 break;
3446 case 0x1e: /* V9 stxa */
6ea4a6c8 3447 gen_op_check_align_T0_7();
81ad8ba2 3448 gen_st_asi(insn, 8);
0f8a249a 3449 break;
3475187d 3450#endif
0f8a249a
BS
3451 default:
3452 goto illegal_insn;
3453 }
3454 } else if (xop > 0x23 && xop < 0x28) {
a80dde08
FB
3455 if (gen_trap_ifnofpu(dc))
3456 goto jmp_insn;
0f8a249a
BS
3457 switch (xop) {
3458 case 0x24:
6ea4a6c8 3459 gen_op_check_align_T0_3();
e8af50a3 3460 gen_op_load_fpr_FT0(rd);
0f8a249a
BS
3461 gen_op_ldst(stf);
3462 break;
3463 case 0x25: /* stfsr, V9 stxfsr */
6ea4a6c8
BS
3464#ifdef CONFIG_USER_ONLY
3465 gen_op_check_align_T0_3();
3466#endif
0f8a249a
BS
3467 gen_op_stfsr();
3468 gen_op_ldst(stf);
3469 break;
1f587329
BS
3470 case 0x26:
3471#ifdef TARGET_SPARC64
3472#if defined(CONFIG_USER_ONLY)
3473 /* V9 stqf, store quad fpreg */
3474 gen_op_check_align_T0_7();
3475 gen_op_load_fpr_QT0(QFPREG(rd));
3476 gen_op_ldst(stqf);
3477 break;
3478#else
3479 goto nfpu_insn;
3480#endif
3481#else /* !TARGET_SPARC64 */
3482 /* stdfq, store floating point queue */
3483#if defined(CONFIG_USER_ONLY)
3484 goto illegal_insn;
3485#else
0f8a249a
BS
3486 if (!supervisor(dc))
3487 goto priv_insn;
3488 if (gen_trap_ifnofpu(dc))
3489 goto jmp_insn;
3490 goto nfq_insn;
1f587329 3491#endif
0f8a249a
BS
3492#endif
3493 case 0x27:
6ea4a6c8 3494 gen_op_check_align_T0_7();
3475187d 3495 gen_op_load_fpr_DT0(DFPREG(rd));
0f8a249a
BS
3496 gen_op_ldst(stdf);
3497 break;
3498 default:
3499 goto illegal_insn;
3500 }
3501 } else if (xop > 0x33 && xop < 0x3f) {
3502 switch (xop) {
a4d17f19 3503#ifdef TARGET_SPARC64
0f8a249a 3504 case 0x34: /* V9 stfa */
6ea4a6c8 3505 gen_op_check_align_T0_3();
3391c818 3506 gen_op_load_fpr_FT0(rd);
2382dc6b 3507 gen_stf_asi(insn, 4, rd);
0f8a249a 3508 break;
1f587329
BS
3509 case 0x36: /* V9 stqfa */
3510#if defined(CONFIG_USER_ONLY)
3511 gen_op_check_align_T0_7();
3512 gen_op_load_fpr_QT0(QFPREG(rd));
2382dc6b 3513 gen_stf_asi(insn, 16, QFPREG(rd));
1f587329
BS
3514 break;
3515#else
3516 goto nfpu_insn;
3517#endif
0f8a249a 3518 case 0x37: /* V9 stdfa */
3391c818
BS
3519 gen_op_check_align_T0_3();
3520 gen_op_load_fpr_DT0(DFPREG(rd));
2382dc6b 3521 gen_stf_asi(insn, 8, DFPREG(rd));
0f8a249a
BS
3522 break;
3523 case 0x3c: /* V9 casa */
6ea4a6c8 3524 gen_op_check_align_T0_3();
81ad8ba2
BS
3525 flush_T2(dc);
3526 gen_movl_reg_T2(rd);
3527 gen_cas_asi(insn);
3528 gen_movl_T1_reg(rd);
0f8a249a
BS
3529 break;
3530 case 0x3e: /* V9 casxa */
6ea4a6c8 3531 gen_op_check_align_T0_7();
81ad8ba2
BS
3532 flush_T2(dc);
3533 gen_movl_reg_T2(rd);
3534 gen_casx_asi(insn);
3535 gen_movl_T1_reg(rd);
0f8a249a 3536 break;
a4d17f19 3537#else
0f8a249a
BS
3538 case 0x34: /* stc */
3539 case 0x35: /* stcsr */
3540 case 0x36: /* stdcq */
3541 case 0x37: /* stdc */
3542 goto ncp_insn;
3543#endif
3544 default:
3545 goto illegal_insn;
3546 }
e8af50a3 3547 }
0f8a249a
BS
3548 else
3549 goto illegal_insn;
3550 }
3551 break;
cf495bcf
FB
3552 }
3553 /* default case for non jump instructions */
72cbca10 3554 if (dc->npc == DYNAMIC_PC) {
0f8a249a
BS
3555 dc->pc = DYNAMIC_PC;
3556 gen_op_next_insn();
72cbca10
FB
3557 } else if (dc->npc == JUMP_PC) {
3558 /* we can do a static jump */
46525e1f 3559 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1]);
72cbca10
FB
3560 dc->is_br = 1;
3561 } else {
0f8a249a
BS
3562 dc->pc = dc->npc;
3563 dc->npc = dc->npc + 4;
cf495bcf 3564 }
e80cfcfc 3565 jmp_insn:
cf495bcf
FB
3566 return;
3567 illegal_insn:
72cbca10 3568 save_state(dc);
cf495bcf
FB
3569 gen_op_exception(TT_ILL_INSN);
3570 dc->is_br = 1;
e8af50a3 3571 return;
e80cfcfc 3572#if !defined(CONFIG_USER_ONLY)
e8af50a3
FB
3573 priv_insn:
3574 save_state(dc);
3575 gen_op_exception(TT_PRIV_INSN);
3576 dc->is_br = 1;
e80cfcfc 3577 return;
e80cfcfc
FB
3578 nfpu_insn:
3579 save_state(dc);
3580 gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
3581 dc->is_br = 1;
fcc72045 3582 return;
1f587329 3583#ifndef TARGET_SPARC64
9143e598
BS
3584 nfq_insn:
3585 save_state(dc);
3586 gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
3587 dc->is_br = 1;
3588 return;
3589#endif
1f587329 3590#endif
fcc72045
BS
3591#ifndef TARGET_SPARC64
3592 ncp_insn:
3593 save_state(dc);
3594 gen_op_exception(TT_NCP_INSN);
3595 dc->is_br = 1;
3596 return;
3597#endif
7a3f1944
FB
3598}
3599
cf495bcf 3600static inline int gen_intermediate_code_internal(TranslationBlock * tb,
0f8a249a 3601 int spc, CPUSPARCState *env)
7a3f1944 3602{
72cbca10 3603 target_ulong pc_start, last_pc;
cf495bcf
FB
3604 uint16_t *gen_opc_end;
3605 DisasContext dc1, *dc = &dc1;
e8af50a3 3606 int j, lj = -1;
cf495bcf
FB
3607
3608 memset(dc, 0, sizeof(DisasContext));
cf495bcf 3609 dc->tb = tb;
72cbca10 3610 pc_start = tb->pc;
cf495bcf 3611 dc->pc = pc_start;
e80cfcfc 3612 last_pc = dc->pc;
72cbca10 3613 dc->npc = (target_ulong) tb->cs_base;
6f27aba6
BS
3614 dc->mem_idx = cpu_mmu_index(env);
3615 dc->fpu_enabled = cpu_fpu_enabled(env);
cf495bcf 3616 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
cf495bcf
FB
3617
3618 do {
e8af50a3
FB
3619 if (env->nb_breakpoints > 0) {
3620 for(j = 0; j < env->nb_breakpoints; j++) {
3621 if (env->breakpoints[j] == dc->pc) {
0f8a249a
BS
3622 if (dc->pc != pc_start)
3623 save_state(dc);
e80cfcfc 3624 gen_op_debug();
57fec1fe 3625 tcg_gen_exit_tb(0);
0f8a249a 3626 dc->is_br = 1;
e80cfcfc 3627 goto exit_gen_loop;
e8af50a3
FB
3628 }
3629 }
3630 }
3631 if (spc) {
3632 if (loglevel > 0)
3633 fprintf(logfile, "Search PC...\n");
3634 j = gen_opc_ptr - gen_opc_buf;
3635 if (lj < j) {
3636 lj++;
3637 while (lj < j)
3638 gen_opc_instr_start[lj++] = 0;
3639 gen_opc_pc[lj] = dc->pc;
3640 gen_opc_npc[lj] = dc->npc;
3641 gen_opc_instr_start[lj] = 1;
3642 }
3643 }
0f8a249a
BS
3644 last_pc = dc->pc;
3645 disas_sparc_insn(dc);
3646
3647 if (dc->is_br)
3648 break;
3649 /* if the next PC is different, we abort now */
3650 if (dc->pc != (last_pc + 4))
3651 break;
d39c0b99
FB
3652 /* if we reach a page boundary, we stop generation so that the
3653 PC of a TT_TFAULT exception is always in the right page */
3654 if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
3655 break;
e80cfcfc
FB
3656 /* if single step mode, we generate only one instruction and
3657 generate an exception */
3658 if (env->singlestep_enabled) {
3475187d 3659 gen_jmp_im(dc->pc);
57fec1fe 3660 tcg_gen_exit_tb(0);
e80cfcfc
FB
3661 break;
3662 }
cf495bcf 3663 } while ((gen_opc_ptr < gen_opc_end) &&
0f8a249a 3664 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
e80cfcfc
FB
3665
3666 exit_gen_loop:
72cbca10 3667 if (!dc->is_br) {
5fafdf24 3668 if (dc->pc != DYNAMIC_PC &&
72cbca10
FB
3669 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
3670 /* static PC and NPC: we can use direct chaining */
46525e1f 3671 gen_branch(dc, dc->pc, dc->npc);
72cbca10
FB
3672 } else {
3673 if (dc->pc != DYNAMIC_PC)
3475187d 3674 gen_jmp_im(dc->pc);
72cbca10 3675 save_npc(dc);
57fec1fe 3676 tcg_gen_exit_tb(0);
72cbca10
FB
3677 }
3678 }
cf495bcf 3679 *gen_opc_ptr = INDEX_op_end;
e8af50a3
FB
3680 if (spc) {
3681 j = gen_opc_ptr - gen_opc_buf;
3682 lj++;
3683 while (lj <= j)
3684 gen_opc_instr_start[lj++] = 0;
e8af50a3
FB
3685#if 0
3686 if (loglevel > 0) {
3687 page_dump(logfile);
3688 }
3689#endif
c3278b7b
FB
3690 gen_opc_jump_pc[0] = dc->jump_pc[0];
3691 gen_opc_jump_pc[1] = dc->jump_pc[1];
e8af50a3 3692 } else {
e80cfcfc 3693 tb->size = last_pc + 4 - pc_start;
e8af50a3 3694 }
7a3f1944 3695#ifdef DEBUG_DISAS
e19e89a5 3696 if (loglevel & CPU_LOG_TB_IN_ASM) {
0f8a249a
BS
3697 fprintf(logfile, "--------------\n");
3698 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3699 target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
3700 fprintf(logfile, "\n");
cf495bcf 3701 }
7a3f1944 3702#endif
cf495bcf 3703 return 0;
7a3f1944
FB
3704}
3705
cf495bcf 3706int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 3707{
e8af50a3 3708 return gen_intermediate_code_internal(tb, 0, env);
7a3f1944
FB
3709}
3710
cf495bcf 3711int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 3712{
e8af50a3 3713 return gen_intermediate_code_internal(tb, 1, env);
7a3f1944
FB
3714}
3715
e80cfcfc
FB
3716void cpu_reset(CPUSPARCState *env)
3717{
bb05683b 3718 tlb_flush(env, 1);
cf495bcf
FB
3719 env->cwp = 0;
3720 env->wim = 1;
3721 env->regwptr = env->regbase + (env->cwp * 16);
e8af50a3 3722#if defined(CONFIG_USER_ONLY)
cf495bcf 3723 env->user_mode_only = 1;
5ef54116 3724#ifdef TARGET_SPARC64
6ef905f6
BS
3725 env->cleanwin = NWINDOWS - 2;
3726 env->cansave = NWINDOWS - 2;
3727 env->pstate = PS_RMO | PS_PEF | PS_IE;
3728 env->asi = 0x82; // Primary no-fault
5ef54116 3729#endif
e8af50a3 3730#else
32af58f9 3731 env->psret = 0;
e8af50a3 3732 env->psrs = 1;
0bee699e 3733 env->psrps = 1;
3475187d 3734#ifdef TARGET_SPARC64
83469015 3735 env->pstate = PS_PRIV;
6f27aba6 3736 env->hpstate = HS_PRIV;
83469015 3737 env->pc = 0x1fff0000000ULL;
3475187d 3738#else
40ce0a9a 3739 env->pc = 0;
32af58f9 3740 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
6d5f237a 3741 env->mmuregs[0] |= env->mmu_bm;
3475187d 3742#endif
83469015 3743 env->npc = env->pc + 4;
e8af50a3 3744#endif
e80cfcfc
FB
3745}
3746
aaed909a 3747CPUSPARCState *cpu_sparc_init(const char *cpu_model)
e80cfcfc
FB
3748{
3749 CPUSPARCState *env;
aaed909a
FB
3750 const sparc_def_t *def;
3751
3752 def = cpu_sparc_find_by_name(cpu_model);
3753 if (!def)
3754 return NULL;
e80cfcfc 3755
c68ea704
FB
3756 env = qemu_mallocz(sizeof(CPUSPARCState));
3757 if (!env)
0f8a249a 3758 return NULL;
c68ea704 3759 cpu_exec_init(env);
01ba9816 3760 env->cpu_model_str = cpu_model;
aaed909a
FB
3761 env->version = def->iu_version;
3762 env->fsr = def->fpu_version;
3763#if !defined(TARGET_SPARC64)
3764 env->mmu_bm = def->mmu_bm;
3deaeab7
BS
3765 env->mmu_ctpr_mask = def->mmu_ctpr_mask;
3766 env->mmu_cxr_mask = def->mmu_cxr_mask;
3767 env->mmu_sfsr_mask = def->mmu_sfsr_mask;
3768 env->mmu_trcr_mask = def->mmu_trcr_mask;
aaed909a
FB
3769 env->mmuregs[0] |= def->mmu_version;
3770 cpu_sparc_set_id(env, 0);
3771#endif
3772 cpu_reset(env);
3773
3774 return env;
3775}
3776
3777void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
3778{
3779#if !defined(TARGET_SPARC64)
3780 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
3781#endif
7a3f1944
FB
3782}
3783
62724a37
BS
3784static const sparc_def_t sparc_defs[] = {
3785#ifdef TARGET_SPARC64
7d77bf20
BS
3786 {
3787 .name = "Fujitsu Sparc64",
3788 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
3789 | (MAXTL << 8) | (NWINDOWS - 1)),
3790 .fpu_version = 0x00000000,
3791 .mmu_version = 0,
3792 },
3793 {
3794 .name = "Fujitsu Sparc64 III",
3795 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
3796 | (MAXTL << 8) | (NWINDOWS - 1)),
3797 .fpu_version = 0x00000000,
3798 .mmu_version = 0,
3799 },
3800 {
3801 .name = "Fujitsu Sparc64 IV",
3802 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
3803 | (MAXTL << 8) | (NWINDOWS - 1)),
3804 .fpu_version = 0x00000000,
3805 .mmu_version = 0,
3806 },
3807 {
3808 .name = "Fujitsu Sparc64 V",
3809 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
3810 | (MAXTL << 8) | (NWINDOWS - 1)),
3811 .fpu_version = 0x00000000,
3812 .mmu_version = 0,
3813 },
3814 {
3815 .name = "TI UltraSparc I",
3816 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
3817 | (MAXTL << 8) | (NWINDOWS - 1)),
3818 .fpu_version = 0x00000000,
3819 .mmu_version = 0,
3820 },
62724a37
BS
3821 {
3822 .name = "TI UltraSparc II",
7d77bf20
BS
3823 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
3824 | (MAXTL << 8) | (NWINDOWS - 1)),
3825 .fpu_version = 0x00000000,
3826 .mmu_version = 0,
3827 },
3828 {
3829 .name = "TI UltraSparc IIi",
3830 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
3831 | (MAXTL << 8) | (NWINDOWS - 1)),
3832 .fpu_version = 0x00000000,
3833 .mmu_version = 0,
3834 },
3835 {
3836 .name = "TI UltraSparc IIe",
3837 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
3838 | (MAXTL << 8) | (NWINDOWS - 1)),
3839 .fpu_version = 0x00000000,
3840 .mmu_version = 0,
3841 },
3842 {
3843 .name = "Sun UltraSparc III",
3844 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
3845 | (MAXTL << 8) | (NWINDOWS - 1)),
3846 .fpu_version = 0x00000000,
3847 .mmu_version = 0,
3848 },
3849 {
3850 .name = "Sun UltraSparc III Cu",
3851 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
3852 | (MAXTL << 8) | (NWINDOWS - 1)),
3853 .fpu_version = 0x00000000,
3854 .mmu_version = 0,
3855 },
3856 {
3857 .name = "Sun UltraSparc IIIi",
3858 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
3859 | (MAXTL << 8) | (NWINDOWS - 1)),
3860 .fpu_version = 0x00000000,
3861 .mmu_version = 0,
3862 },
3863 {
3864 .name = "Sun UltraSparc IV",
3865 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
3866 | (MAXTL << 8) | (NWINDOWS - 1)),
3867 .fpu_version = 0x00000000,
3868 .mmu_version = 0,
3869 },
3870 {
3871 .name = "Sun UltraSparc IV+",
3872 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
3873 | (MAXTL << 8) | (NWINDOWS - 1)),
3874 .fpu_version = 0x00000000,
3875 .mmu_version = 0,
3876 },
3877 {
3878 .name = "Sun UltraSparc IIIi+",
3879 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
3880 | (MAXTL << 8) | (NWINDOWS - 1)),
3881 .fpu_version = 0x00000000,
3882 .mmu_version = 0,
3883 },
3884 {
3885 .name = "NEC UltraSparc I",
3886 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
62724a37
BS
3887 | (MAXTL << 8) | (NWINDOWS - 1)),
3888 .fpu_version = 0x00000000,
3889 .mmu_version = 0,
3890 },
3891#else
406f82e8
BS
3892 {
3893 .name = "Fujitsu MB86900",
3894 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
3895 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
3896 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
3897 .mmu_bm = 0x00004000,
3deaeab7
BS
3898 .mmu_ctpr_mask = 0x007ffff0,
3899 .mmu_cxr_mask = 0x0000003f,
3900 .mmu_sfsr_mask = 0xffffffff,
3901 .mmu_trcr_mask = 0xffffffff,
406f82e8 3902 },
62724a37
BS
3903 {
3904 .name = "Fujitsu MB86904",
3905 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
3906 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
3907 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
6d5f237a 3908 .mmu_bm = 0x00004000,
3deaeab7
BS
3909 .mmu_ctpr_mask = 0x00ffffc0,
3910 .mmu_cxr_mask = 0x000000ff,
3911 .mmu_sfsr_mask = 0x00016fff,
3912 .mmu_trcr_mask = 0x00ffffff,
62724a37 3913 },
e0353fe2 3914 {
5ef62c5c
BS
3915 .name = "Fujitsu MB86907",
3916 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
3917 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
3918 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
6d5f237a 3919 .mmu_bm = 0x00004000,
3deaeab7
BS
3920 .mmu_ctpr_mask = 0xffffffc0,
3921 .mmu_cxr_mask = 0x000000ff,
3922 .mmu_sfsr_mask = 0x00016fff,
3923 .mmu_trcr_mask = 0xffffffff,
5ef62c5c 3924 },
406f82e8
BS
3925 {
3926 .name = "LSI L64811",
3927 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
3928 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
3929 .mmu_version = 0x10 << 24,
3930 .mmu_bm = 0x00004000,
3deaeab7
BS
3931 .mmu_ctpr_mask = 0x007ffff0,
3932 .mmu_cxr_mask = 0x0000003f,
3933 .mmu_sfsr_mask = 0xffffffff,
3934 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
3935 },
3936 {
3937 .name = "Cypress CY7C601",
3938 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
3939 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
3940 .mmu_version = 0x10 << 24,
3941 .mmu_bm = 0x00004000,
3deaeab7
BS
3942 .mmu_ctpr_mask = 0x007ffff0,
3943 .mmu_cxr_mask = 0x0000003f,
3944 .mmu_sfsr_mask = 0xffffffff,
3945 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
3946 },
3947 {
3948 .name = "Cypress CY7C611",
3949 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
3950 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
3951 .mmu_version = 0x10 << 24,
3952 .mmu_bm = 0x00004000,
3deaeab7
BS
3953 .mmu_ctpr_mask = 0x007ffff0,
3954 .mmu_cxr_mask = 0x0000003f,
3955 .mmu_sfsr_mask = 0xffffffff,
3956 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
3957 },
3958 {
3959 .name = "TI SuperSparc II",
3960 .iu_version = 0x40000000,
3961 .fpu_version = 0 << 17,
3962 .mmu_version = 0x04000000,
3963 .mmu_bm = 0x00002000,
3deaeab7
BS
3964 .mmu_ctpr_mask = 0xffffffc0,
3965 .mmu_cxr_mask = 0x0000ffff,
3966 .mmu_sfsr_mask = 0xffffffff,
3967 .mmu_trcr_mask = 0xffffffff,
406f82e8 3968 },
5ef62c5c
BS
3969 {
3970 .name = "TI MicroSparc I",
3971 .iu_version = 0x41000000,
3972 .fpu_version = 4 << 17,
3973 .mmu_version = 0x41000000,
6d5f237a 3974 .mmu_bm = 0x00004000,
3deaeab7
BS
3975 .mmu_ctpr_mask = 0x007ffff0,
3976 .mmu_cxr_mask = 0x0000003f,
3977 .mmu_sfsr_mask = 0x00016fff,
3978 .mmu_trcr_mask = 0x0000003f,
5ef62c5c
BS
3979 },
3980 {
406f82e8
BS
3981 .name = "TI MicroSparc II",
3982 .iu_version = 0x42000000,
3983 .fpu_version = 4 << 17,
3984 .mmu_version = 0x02000000,
3985 .mmu_bm = 0x00004000,
3deaeab7
BS
3986 .mmu_ctpr_mask = 0x00ffffc0,
3987 .mmu_cxr_mask = 0x000000ff,
3988 .mmu_sfsr_mask = 0x00016bff,
3989 .mmu_trcr_mask = 0x00ffffff,
406f82e8
BS
3990 },
3991 {
3992 .name = "TI MicroSparc IIep",
3993 .iu_version = 0x42000000,
3994 .fpu_version = 4 << 17,
3995 .mmu_version = 0x04000000,
3996 .mmu_bm = 0x00004000,
3deaeab7
BS
3997 .mmu_ctpr_mask = 0x00ffffc0,
3998 .mmu_cxr_mask = 0x000000ff,
3999 .mmu_sfsr_mask = 0x00016bff,
4000 .mmu_trcr_mask = 0x00ffffff,
406f82e8
BS
4001 },
4002 {
4003 .name = "TI SuperSparc 51",
4004 .iu_version = 0x43000000,
5ef62c5c
BS
4005 .fpu_version = 0 << 17,
4006 .mmu_version = 0x04000000,
6d5f237a 4007 .mmu_bm = 0x00002000,
3deaeab7
BS
4008 .mmu_ctpr_mask = 0xffffffc0,
4009 .mmu_cxr_mask = 0x0000ffff,
4010 .mmu_sfsr_mask = 0xffffffff,
4011 .mmu_trcr_mask = 0xffffffff,
5ef62c5c
BS
4012 },
4013 {
406f82e8
BS
4014 .name = "TI SuperSparc 61",
4015 .iu_version = 0x44000000,
4016 .fpu_version = 0 << 17,
4017 .mmu_version = 0x04000000,
4018 .mmu_bm = 0x00002000,
3deaeab7
BS
4019 .mmu_ctpr_mask = 0xffffffc0,
4020 .mmu_cxr_mask = 0x0000ffff,
4021 .mmu_sfsr_mask = 0xffffffff,
4022 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4023 },
4024 {
4025 .name = "Ross RT625",
5ef62c5c
BS
4026 .iu_version = 0x1e000000,
4027 .fpu_version = 1 << 17,
406f82e8
BS
4028 .mmu_version = 0x1e000000,
4029 .mmu_bm = 0x00004000,
3deaeab7
BS
4030 .mmu_ctpr_mask = 0x007ffff0,
4031 .mmu_cxr_mask = 0x0000003f,
4032 .mmu_sfsr_mask = 0xffffffff,
4033 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4034 },
4035 {
4036 .name = "Ross RT620",
4037 .iu_version = 0x1f000000,
4038 .fpu_version = 1 << 17,
4039 .mmu_version = 0x1f000000,
4040 .mmu_bm = 0x00004000,
3deaeab7
BS
4041 .mmu_ctpr_mask = 0x007ffff0,
4042 .mmu_cxr_mask = 0x0000003f,
4043 .mmu_sfsr_mask = 0xffffffff,
4044 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4045 },
4046 {
4047 .name = "BIT B5010",
4048 .iu_version = 0x20000000,
4049 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
4050 .mmu_version = 0x20000000,
4051 .mmu_bm = 0x00004000,
3deaeab7
BS
4052 .mmu_ctpr_mask = 0x007ffff0,
4053 .mmu_cxr_mask = 0x0000003f,
4054 .mmu_sfsr_mask = 0xffffffff,
4055 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4056 },
4057 {
4058 .name = "Matsushita MN10501",
4059 .iu_version = 0x50000000,
4060 .fpu_version = 0 << 17,
4061 .mmu_version = 0x50000000,
4062 .mmu_bm = 0x00004000,
3deaeab7
BS
4063 .mmu_ctpr_mask = 0x007ffff0,
4064 .mmu_cxr_mask = 0x0000003f,
4065 .mmu_sfsr_mask = 0xffffffff,
4066 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4067 },
4068 {
4069 .name = "Weitek W8601",
4070 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
4071 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
4072 .mmu_version = 0x10 << 24,
4073 .mmu_bm = 0x00004000,
3deaeab7
BS
4074 .mmu_ctpr_mask = 0x007ffff0,
4075 .mmu_cxr_mask = 0x0000003f,
4076 .mmu_sfsr_mask = 0xffffffff,
4077 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4078 },
4079 {
4080 .name = "LEON2",
4081 .iu_version = 0xf2000000,
4082 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
4083 .mmu_version = 0xf2000000,
4084 .mmu_bm = 0x00004000,
3deaeab7
BS
4085 .mmu_ctpr_mask = 0x007ffff0,
4086 .mmu_cxr_mask = 0x0000003f,
4087 .mmu_sfsr_mask = 0xffffffff,
4088 .mmu_trcr_mask = 0xffffffff,
406f82e8
BS
4089 },
4090 {
4091 .name = "LEON3",
4092 .iu_version = 0xf3000000,
4093 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
4094 .mmu_version = 0xf3000000,
6d5f237a 4095 .mmu_bm = 0x00004000,
3deaeab7
BS
4096 .mmu_ctpr_mask = 0x007ffff0,
4097 .mmu_cxr_mask = 0x0000003f,
4098 .mmu_sfsr_mask = 0xffffffff,
4099 .mmu_trcr_mask = 0xffffffff,
e0353fe2 4100 },
62724a37
BS
4101#endif
4102};
4103
aaed909a 4104static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name)
62724a37 4105{
62724a37
BS
4106 unsigned int i;
4107
62724a37
BS
4108 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
4109 if (strcasecmp(name, sparc_defs[i].name) == 0) {
aaed909a 4110 return &sparc_defs[i];
62724a37
BS
4111 }
4112 }
aaed909a 4113 return NULL;
62724a37
BS
4114}
4115
4116void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
4117{
4118 unsigned int i;
4119
4120 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
4121 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
4122 sparc_defs[i].name,
4123 sparc_defs[i].iu_version,
4124 sparc_defs[i].fpu_version,
4125 sparc_defs[i].mmu_version);
4126 }
4127}
4128
7a3f1944
FB
4129#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
4130
5fafdf24 4131void cpu_dump_state(CPUState *env, FILE *f,
7fe48483
FB
4132 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4133 int flags)
7a3f1944 4134{
cf495bcf
FB
4135 int i, x;
4136
af7bf89b 4137 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
7fe48483 4138 cpu_fprintf(f, "General Registers:\n");
cf495bcf 4139 for (i = 0; i < 4; i++)
0f8a249a 4140 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
7fe48483 4141 cpu_fprintf(f, "\n");
cf495bcf 4142 for (; i < 8; i++)
0f8a249a 4143 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
7fe48483 4144 cpu_fprintf(f, "\nCurrent Register Window:\n");
cf495bcf 4145 for (x = 0; x < 3; x++) {
0f8a249a
BS
4146 for (i = 0; i < 4; i++)
4147 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
4148 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
4149 env->regwptr[i + x * 8]);
4150 cpu_fprintf(f, "\n");
4151 for (; i < 8; i++)
4152 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
4153 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
4154 env->regwptr[i + x * 8]);
4155 cpu_fprintf(f, "\n");
cf495bcf 4156 }
7fe48483 4157 cpu_fprintf(f, "\nFloating Point Registers:\n");
e8af50a3
FB
4158 for (i = 0; i < 32; i++) {
4159 if ((i & 3) == 0)
7fe48483
FB
4160 cpu_fprintf(f, "%%f%02d:", i);
4161 cpu_fprintf(f, " %016lf", env->fpr[i]);
e8af50a3 4162 if ((i & 3) == 3)
7fe48483 4163 cpu_fprintf(f, "\n");
e8af50a3 4164 }
ded3ab80 4165#ifdef TARGET_SPARC64
3299908c 4166 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
0f8a249a 4167 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
ded3ab80 4168 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
0f8a249a
BS
4169 env->cansave, env->canrestore, env->otherwin, env->wstate,
4170 env->cleanwin, NWINDOWS - 1 - env->cwp);
ded3ab80 4171#else
7fe48483 4172 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
0f8a249a
BS
4173 GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
4174 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
4175 env->psrs?'S':'-', env->psrps?'P':'-',
4176 env->psret?'E':'-', env->wim);
ded3ab80 4177#endif
3475187d 4178 cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
7a3f1944 4179}
edfcbd99 4180
e80cfcfc 4181#if defined(CONFIG_USER_ONLY)
9b3c35e0 4182target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
edfcbd99
FB
4183{
4184 return addr;
4185}
658138bc 4186
e80cfcfc 4187#else
af7bf89b
FB
4188extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
4189 int *access_index, target_ulong address, int rw,
6ebbf390 4190 int mmu_idx);
0fa85d43 4191
9b3c35e0 4192target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
e80cfcfc 4193{
af7bf89b 4194 target_phys_addr_t phys_addr;
e80cfcfc
FB
4195 int prot, access_index;
4196
9e31b9e2
BS
4197 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
4198 MMU_KERNEL_IDX) != 0)
4199 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
4200 0, MMU_KERNEL_IDX) != 0)
6b1575b7 4201 return -1;
6c36d3fa
BS
4202 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
4203 return -1;
e80cfcfc
FB
4204 return phys_addr;
4205}
4206#endif
4207
658138bc
FB
4208void helper_flush(target_ulong addr)
4209{
4210 addr &= ~7;
4211 tb_invalidate_page_range(addr, addr + 8);
4212}