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