Squash logic bugs while they are fresh...
[qemu] / target-sparc / translate.c
1 /*
2    SPARC translation
3
4    Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5    Copyright (C) 2003-2005 Fabrice Bellard
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2 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    Optional alignment check
29    128-bit float
30 */
31
32 #include <stdarg.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <inttypes.h>
37
38 #include "cpu.h"
39 #include "exec-all.h"
40 #include "disas.h"
41
42 #define DEBUG_DISAS
43
44 #define DYNAMIC_PC  1 /* dynamic pc value */
45 #define JUMP_PC     2 /* dynamic pc value which takes only two values
46                          according to jump_pc[T2] */
47
48 typedef struct DisasContext {
49     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
50     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
51     target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
52     int is_br;
53     int mem_idx;
54     int fpu_enabled;
55     struct TranslationBlock *tb;
56 } DisasContext;
57
58 struct sparc_def_t {
59     const unsigned char *name;
60     target_ulong iu_version;
61     uint32_t fpu_version;
62     uint32_t mmu_version;
63 };
64
65 static uint16_t *gen_opc_ptr;
66 static uint32_t *gen_opparam_ptr;
67 extern FILE *logfile;
68 extern int loglevel;
69
70 enum {
71 #define DEF(s,n,copy_size) INDEX_op_ ## s,
72 #include "opc.h"
73 #undef DEF
74     NB_OPS
75 };
76
77 #include "gen-op.h"
78
79 // This function uses non-native bit order
80 #define GET_FIELD(X, FROM, TO) \
81   ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
82
83 // This function uses the order in the manuals, i.e. bit 0 is 2^0
84 #define GET_FIELD_SP(X, FROM, TO) \
85     GET_FIELD(X, 31 - (TO), 31 - (FROM))
86
87 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
88 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), 32 - ((b) - (a) + 1))
89
90 #ifdef TARGET_SPARC64
91 #define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
92 #else
93 #define DFPREG(r) (r)
94 #endif
95
96 #ifdef USE_DIRECT_JUMP
97 #define TBPARAM(x)
98 #else
99 #define TBPARAM(x) (long)(x)
100 #endif
101
102 static int sign_extend(int x, int len)
103 {
104     len = 32 - len;
105     return (x << len) >> len;
106 }
107
108 #define IS_IMM (insn & (1<<13))
109
110 static void disas_sparc_insn(DisasContext * dc);
111
112 static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
113     {
114      gen_op_movl_g0_T0,
115      gen_op_movl_g1_T0,
116      gen_op_movl_g2_T0,
117      gen_op_movl_g3_T0,
118      gen_op_movl_g4_T0,
119      gen_op_movl_g5_T0,
120      gen_op_movl_g6_T0,
121      gen_op_movl_g7_T0,
122      gen_op_movl_o0_T0,
123      gen_op_movl_o1_T0,
124      gen_op_movl_o2_T0,
125      gen_op_movl_o3_T0,
126      gen_op_movl_o4_T0,
127      gen_op_movl_o5_T0,
128      gen_op_movl_o6_T0,
129      gen_op_movl_o7_T0,
130      gen_op_movl_l0_T0,
131      gen_op_movl_l1_T0,
132      gen_op_movl_l2_T0,
133      gen_op_movl_l3_T0,
134      gen_op_movl_l4_T0,
135      gen_op_movl_l5_T0,
136      gen_op_movl_l6_T0,
137      gen_op_movl_l7_T0,
138      gen_op_movl_i0_T0,
139      gen_op_movl_i1_T0,
140      gen_op_movl_i2_T0,
141      gen_op_movl_i3_T0,
142      gen_op_movl_i4_T0,
143      gen_op_movl_i5_T0,
144      gen_op_movl_i6_T0,
145      gen_op_movl_i7_T0,
146      },
147     {
148      gen_op_movl_g0_T1,
149      gen_op_movl_g1_T1,
150      gen_op_movl_g2_T1,
151      gen_op_movl_g3_T1,
152      gen_op_movl_g4_T1,
153      gen_op_movl_g5_T1,
154      gen_op_movl_g6_T1,
155      gen_op_movl_g7_T1,
156      gen_op_movl_o0_T1,
157      gen_op_movl_o1_T1,
158      gen_op_movl_o2_T1,
159      gen_op_movl_o3_T1,
160      gen_op_movl_o4_T1,
161      gen_op_movl_o5_T1,
162      gen_op_movl_o6_T1,
163      gen_op_movl_o7_T1,
164      gen_op_movl_l0_T1,
165      gen_op_movl_l1_T1,
166      gen_op_movl_l2_T1,
167      gen_op_movl_l3_T1,
168      gen_op_movl_l4_T1,
169      gen_op_movl_l5_T1,
170      gen_op_movl_l6_T1,
171      gen_op_movl_l7_T1,
172      gen_op_movl_i0_T1,
173      gen_op_movl_i1_T1,
174      gen_op_movl_i2_T1,
175      gen_op_movl_i3_T1,
176      gen_op_movl_i4_T1,
177      gen_op_movl_i5_T1,
178      gen_op_movl_i6_T1,
179      gen_op_movl_i7_T1,
180      }
181 };
182
183 static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
184     {
185      gen_op_movl_T0_g0,
186      gen_op_movl_T0_g1,
187      gen_op_movl_T0_g2,
188      gen_op_movl_T0_g3,
189      gen_op_movl_T0_g4,
190      gen_op_movl_T0_g5,
191      gen_op_movl_T0_g6,
192      gen_op_movl_T0_g7,
193      gen_op_movl_T0_o0,
194      gen_op_movl_T0_o1,
195      gen_op_movl_T0_o2,
196      gen_op_movl_T0_o3,
197      gen_op_movl_T0_o4,
198      gen_op_movl_T0_o5,
199      gen_op_movl_T0_o6,
200      gen_op_movl_T0_o7,
201      gen_op_movl_T0_l0,
202      gen_op_movl_T0_l1,
203      gen_op_movl_T0_l2,
204      gen_op_movl_T0_l3,
205      gen_op_movl_T0_l4,
206      gen_op_movl_T0_l5,
207      gen_op_movl_T0_l6,
208      gen_op_movl_T0_l7,
209      gen_op_movl_T0_i0,
210      gen_op_movl_T0_i1,
211      gen_op_movl_T0_i2,
212      gen_op_movl_T0_i3,
213      gen_op_movl_T0_i4,
214      gen_op_movl_T0_i5,
215      gen_op_movl_T0_i6,
216      gen_op_movl_T0_i7,
217      },
218     {
219      gen_op_movl_T1_g0,
220      gen_op_movl_T1_g1,
221      gen_op_movl_T1_g2,
222      gen_op_movl_T1_g3,
223      gen_op_movl_T1_g4,
224      gen_op_movl_T1_g5,
225      gen_op_movl_T1_g6,
226      gen_op_movl_T1_g7,
227      gen_op_movl_T1_o0,
228      gen_op_movl_T1_o1,
229      gen_op_movl_T1_o2,
230      gen_op_movl_T1_o3,
231      gen_op_movl_T1_o4,
232      gen_op_movl_T1_o5,
233      gen_op_movl_T1_o6,
234      gen_op_movl_T1_o7,
235      gen_op_movl_T1_l0,
236      gen_op_movl_T1_l1,
237      gen_op_movl_T1_l2,
238      gen_op_movl_T1_l3,
239      gen_op_movl_T1_l4,
240      gen_op_movl_T1_l5,
241      gen_op_movl_T1_l6,
242      gen_op_movl_T1_l7,
243      gen_op_movl_T1_i0,
244      gen_op_movl_T1_i1,
245      gen_op_movl_T1_i2,
246      gen_op_movl_T1_i3,
247      gen_op_movl_T1_i4,
248      gen_op_movl_T1_i5,
249      gen_op_movl_T1_i6,
250      gen_op_movl_T1_i7,
251      },
252     {
253      gen_op_movl_T2_g0,
254      gen_op_movl_T2_g1,
255      gen_op_movl_T2_g2,
256      gen_op_movl_T2_g3,
257      gen_op_movl_T2_g4,
258      gen_op_movl_T2_g5,
259      gen_op_movl_T2_g6,
260      gen_op_movl_T2_g7,
261      gen_op_movl_T2_o0,
262      gen_op_movl_T2_o1,
263      gen_op_movl_T2_o2,
264      gen_op_movl_T2_o3,
265      gen_op_movl_T2_o4,
266      gen_op_movl_T2_o5,
267      gen_op_movl_T2_o6,
268      gen_op_movl_T2_o7,
269      gen_op_movl_T2_l0,
270      gen_op_movl_T2_l1,
271      gen_op_movl_T2_l2,
272      gen_op_movl_T2_l3,
273      gen_op_movl_T2_l4,
274      gen_op_movl_T2_l5,
275      gen_op_movl_T2_l6,
276      gen_op_movl_T2_l7,
277      gen_op_movl_T2_i0,
278      gen_op_movl_T2_i1,
279      gen_op_movl_T2_i2,
280      gen_op_movl_T2_i3,
281      gen_op_movl_T2_i4,
282      gen_op_movl_T2_i5,
283      gen_op_movl_T2_i6,
284      gen_op_movl_T2_i7,
285      }
286 };
287
288 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
289     gen_op_movl_T0_im,
290     gen_op_movl_T1_im,
291     gen_op_movl_T2_im
292 };
293
294 // Sign extending version
295 static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
296     gen_op_movl_T0_sim,
297     gen_op_movl_T1_sim,
298     gen_op_movl_T2_sim
299 };
300
301 #ifdef TARGET_SPARC64
302 #define GEN32(func, NAME) \
303 static GenOpFunc *NAME ## _table [64] = {                                     \
304 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
305 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
306 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
307 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
308 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
309 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
310 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
311 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
312 NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0,                   \
313 NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0,                   \
314 NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0,                   \
315 NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0,                   \
316 };                                                                            \
317 static inline void func(int n)                                                \
318 {                                                                             \
319     NAME ## _table[n]();                                                      \
320 }
321 #else
322 #define GEN32(func, NAME) \
323 static GenOpFunc *NAME ## _table [32] = {                                     \
324 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
325 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
326 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
327 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
328 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
329 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
330 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
331 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
332 };                                                                            \
333 static inline void func(int n)                                                \
334 {                                                                             \
335     NAME ## _table[n]();                                                      \
336 }
337 #endif
338
339 /* floating point registers moves */
340 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
341 GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
342 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
343 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
344
345 GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
346 GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
347 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
348 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
349
350 #ifdef TARGET_SPARC64
351 // 'a' versions allowed to user depending on asi
352 #if defined(CONFIG_USER_ONLY)
353 #define supervisor(dc) 0
354 #define gen_op_ldst(name)        gen_op_##name##_raw()
355 #define OP_LD_TABLE(width)                                              \
356     static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
357     {                                                                   \
358         int asi, offset;                                                \
359                                                                         \
360         if (IS_IMM) {                                                   \
361             offset = GET_FIELD(insn, 25, 31);                           \
362             if (is_ld)                                                  \
363                 gen_op_ld_asi_reg(offset, size, sign);                  \
364             else                                                        \
365                 gen_op_st_asi_reg(offset, size, sign);                  \
366             return;                                                     \
367         }                                                               \
368         asi = GET_FIELD(insn, 19, 26);                                  \
369         switch (asi) {                                                  \
370         case 0x80: /* Primary address space */                          \
371             gen_op_##width##_raw();                                     \
372             break;                                                      \
373         case 0x82: /* Primary address space, non-faulting load */       \
374             gen_op_##width##_raw();                                     \
375             break;                                                      \
376         default:                                                        \
377             break;                                                      \
378         }                                                               \
379     }
380
381 #else
382 #define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
383 #define OP_LD_TABLE(width)                                              \
384     static GenOpFunc *gen_op_##width[] = {                              \
385         &gen_op_##width##_user,                                         \
386         &gen_op_##width##_kernel,                                       \
387     };                                                                  \
388                                                                         \
389     static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
390     {                                                                   \
391         int asi, offset;                                                \
392                                                                         \
393         if (IS_IMM) {                                                   \
394             offset = GET_FIELD(insn, 25, 31);                           \
395             if (is_ld)                                                  \
396                 gen_op_ld_asi_reg(offset, size, sign);                  \
397             else                                                        \
398                 gen_op_st_asi_reg(offset, size, sign);                  \
399             return;                                                     \
400         }                                                               \
401         asi = GET_FIELD(insn, 19, 26);                                  \
402         if (is_ld)                                                      \
403             gen_op_ld_asi(asi, size, sign);                             \
404         else                                                            \
405             gen_op_st_asi(asi, size, sign);                             \
406     }
407
408 #define supervisor(dc) (dc->mem_idx == 1)
409 #endif
410 #else
411 #if defined(CONFIG_USER_ONLY)
412 #define gen_op_ldst(name)        gen_op_##name##_raw()
413 #define OP_LD_TABLE(width)
414 #define supervisor(dc) 0
415 #else
416 #define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
417 #define OP_LD_TABLE(width)                                                    \
418 static GenOpFunc *gen_op_##width[] = {                                        \
419     &gen_op_##width##_user,                                                   \
420     &gen_op_##width##_kernel,                                                 \
421 };                                                                            \
422                                                                               \
423 static void gen_op_##width##a(int insn, int is_ld, int size, int sign)        \
424 {                                                                             \
425     int asi;                                                                  \
426                                                                               \
427     asi = GET_FIELD(insn, 19, 26);                                            \
428     switch (asi) {                                                            \
429         case 10: /* User data access */                                       \
430             gen_op_##width##_user();                                          \
431             break;                                                            \
432         case 11: /* Supervisor data access */                                 \
433             gen_op_##width##_kernel();                                        \
434             break;                                                            \
435         case 0x20 ... 0x2f: /* MMU passthrough */                             \
436             if (is_ld)                                                        \
437                 gen_op_ld_asi(asi, size, sign);                               \
438             else                                                              \
439                 gen_op_st_asi(asi, size, sign);                               \
440             break;                                                            \
441         default:                                                              \
442             if (is_ld)                                                        \
443                 gen_op_ld_asi(asi, size, sign);                               \
444             else                                                              \
445                 gen_op_st_asi(asi, size, sign);                               \
446             break;                                                            \
447     }                                                                         \
448 }
449
450 #define supervisor(dc) (dc->mem_idx == 1)
451 #endif
452 #endif
453
454 OP_LD_TABLE(ld);
455 OP_LD_TABLE(st);
456 OP_LD_TABLE(ldub);
457 OP_LD_TABLE(lduh);
458 OP_LD_TABLE(ldsb);
459 OP_LD_TABLE(ldsh);
460 OP_LD_TABLE(stb);
461 OP_LD_TABLE(sth);
462 OP_LD_TABLE(std);
463 OP_LD_TABLE(ldstub);
464 OP_LD_TABLE(swap);
465 OP_LD_TABLE(ldd);
466 OP_LD_TABLE(stf);
467 OP_LD_TABLE(stdf);
468 OP_LD_TABLE(ldf);
469 OP_LD_TABLE(lddf);
470
471 #ifdef TARGET_SPARC64
472 OP_LD_TABLE(ldsw);
473 OP_LD_TABLE(ldx);
474 OP_LD_TABLE(stx);
475 OP_LD_TABLE(cas);
476 OP_LD_TABLE(casx);
477 #endif
478
479 static inline void gen_movl_imm_TN(int reg, uint32_t imm)
480 {
481     gen_op_movl_TN_im[reg](imm);
482 }
483
484 static inline void gen_movl_imm_T1(uint32_t val)
485 {
486     gen_movl_imm_TN(1, val);
487 }
488
489 static inline void gen_movl_imm_T0(uint32_t val)
490 {
491     gen_movl_imm_TN(0, val);
492 }
493
494 static inline void gen_movl_simm_TN(int reg, int32_t imm)
495 {
496     gen_op_movl_TN_sim[reg](imm);
497 }
498
499 static inline void gen_movl_simm_T1(int32_t val)
500 {
501     gen_movl_simm_TN(1, val);
502 }
503
504 static inline void gen_movl_simm_T0(int32_t val)
505 {
506     gen_movl_simm_TN(0, val);
507 }
508
509 static inline void gen_movl_reg_TN(int reg, int t)
510 {
511     if (reg)
512         gen_op_movl_reg_TN[t][reg] ();
513     else
514         gen_movl_imm_TN(t, 0);
515 }
516
517 static inline void gen_movl_reg_T0(int reg)
518 {
519     gen_movl_reg_TN(reg, 0);
520 }
521
522 static inline void gen_movl_reg_T1(int reg)
523 {
524     gen_movl_reg_TN(reg, 1);
525 }
526
527 static inline void gen_movl_reg_T2(int reg)
528 {
529     gen_movl_reg_TN(reg, 2);
530 }
531
532 static inline void gen_movl_TN_reg(int reg, int t)
533 {
534     if (reg)
535         gen_op_movl_TN_reg[t][reg] ();
536 }
537
538 static inline void gen_movl_T0_reg(int reg)
539 {
540     gen_movl_TN_reg(reg, 0);
541 }
542
543 static inline void gen_movl_T1_reg(int reg)
544 {
545     gen_movl_TN_reg(reg, 1);
546 }
547
548 static inline void gen_jmp_im(target_ulong pc)
549 {
550 #ifdef TARGET_SPARC64
551     if (pc == (uint32_t)pc) {
552         gen_op_jmp_im(pc);
553     } else {
554         gen_op_jmp_im64(pc >> 32, pc);
555     }
556 #else
557     gen_op_jmp_im(pc);
558 #endif
559 }
560
561 static inline void gen_movl_npc_im(target_ulong npc)
562 {
563 #ifdef TARGET_SPARC64
564     if (npc == (uint32_t)npc) {
565         gen_op_movl_npc_im(npc);
566     } else {
567         gen_op_movq_npc_im64(npc >> 32, npc);
568     }
569 #else
570     gen_op_movl_npc_im(npc);
571 #endif
572 }
573
574 static inline void gen_goto_tb(DisasContext *s, int tb_num, 
575                                target_ulong pc, target_ulong npc)
576 {
577     TranslationBlock *tb;
578
579     tb = s->tb;
580     if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
581         (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK))  {
582         /* jump to same page: we can use a direct jump */
583         if (tb_num == 0)
584             gen_op_goto_tb0(TBPARAM(tb));
585         else
586             gen_op_goto_tb1(TBPARAM(tb));
587         gen_jmp_im(pc);
588         gen_movl_npc_im(npc);
589         gen_op_movl_T0_im((long)tb + tb_num);
590         gen_op_exit_tb();
591     } else {
592         /* jump to another page: currently not optimized */
593         gen_jmp_im(pc);
594         gen_movl_npc_im(npc);
595         gen_op_movl_T0_0();
596         gen_op_exit_tb();
597     }
598 }
599
600 static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
601 {
602     int l1;
603
604     l1 = gen_new_label();
605
606     gen_op_jz_T2_label(l1);
607
608     gen_goto_tb(dc, 0, pc1, pc1 + 4);
609
610     gen_set_label(l1);
611     gen_goto_tb(dc, 1, pc2, pc2 + 4);
612 }
613
614 static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
615 {
616     int l1;
617
618     l1 = gen_new_label();
619
620     gen_op_jz_T2_label(l1);
621
622     gen_goto_tb(dc, 0, pc2, pc1);
623
624     gen_set_label(l1);
625     gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
626 }
627
628 static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
629 {
630     gen_goto_tb(dc, 0, pc, npc);
631 }
632
633 static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2)
634 {
635     int l1, l2;
636
637     l1 = gen_new_label();
638     l2 = gen_new_label();
639     gen_op_jz_T2_label(l1);
640
641     gen_movl_npc_im(npc1);
642     gen_op_jmp_label(l2);
643
644     gen_set_label(l1);
645     gen_movl_npc_im(npc2);
646     gen_set_label(l2);
647 }
648
649 /* call this function before using T2 as it may have been set for a jump */
650 static inline void flush_T2(DisasContext * dc)
651 {
652     if (dc->npc == JUMP_PC) {
653         gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
654         dc->npc = DYNAMIC_PC;
655     }
656 }
657
658 static inline void save_npc(DisasContext * dc)
659 {
660     if (dc->npc == JUMP_PC) {
661         gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
662         dc->npc = DYNAMIC_PC;
663     } else if (dc->npc != DYNAMIC_PC) {
664         gen_movl_npc_im(dc->npc);
665     }
666 }
667
668 static inline void save_state(DisasContext * dc)
669 {
670     gen_jmp_im(dc->pc);
671     save_npc(dc);
672 }
673
674 static inline void gen_mov_pc_npc(DisasContext * dc)
675 {
676     if (dc->npc == JUMP_PC) {
677         gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
678         gen_op_mov_pc_npc();
679         dc->pc = DYNAMIC_PC;
680     } else if (dc->npc == DYNAMIC_PC) {
681         gen_op_mov_pc_npc();
682         dc->pc = DYNAMIC_PC;
683     } else {
684         dc->pc = dc->npc;
685     }
686 }
687
688 static GenOpFunc * const gen_cond[2][16] = {
689     {
690         gen_op_eval_bn,
691         gen_op_eval_be,
692         gen_op_eval_ble,
693         gen_op_eval_bl,
694         gen_op_eval_bleu,
695         gen_op_eval_bcs,
696         gen_op_eval_bneg,
697         gen_op_eval_bvs,
698         gen_op_eval_ba,
699         gen_op_eval_bne,
700         gen_op_eval_bg,
701         gen_op_eval_bge,
702         gen_op_eval_bgu,
703         gen_op_eval_bcc,
704         gen_op_eval_bpos,
705         gen_op_eval_bvc,
706     },
707     {
708 #ifdef TARGET_SPARC64
709         gen_op_eval_bn,
710         gen_op_eval_xbe,
711         gen_op_eval_xble,
712         gen_op_eval_xbl,
713         gen_op_eval_xbleu,
714         gen_op_eval_xbcs,
715         gen_op_eval_xbneg,
716         gen_op_eval_xbvs,
717         gen_op_eval_ba,
718         gen_op_eval_xbne,
719         gen_op_eval_xbg,
720         gen_op_eval_xbge,
721         gen_op_eval_xbgu,
722         gen_op_eval_xbcc,
723         gen_op_eval_xbpos,
724         gen_op_eval_xbvc,
725 #endif
726     },
727 };
728
729 static GenOpFunc * const gen_fcond[4][16] = {
730     {
731         gen_op_eval_bn,
732         gen_op_eval_fbne,
733         gen_op_eval_fblg,
734         gen_op_eval_fbul,
735         gen_op_eval_fbl,
736         gen_op_eval_fbug,
737         gen_op_eval_fbg,
738         gen_op_eval_fbu,
739         gen_op_eval_ba,
740         gen_op_eval_fbe,
741         gen_op_eval_fbue,
742         gen_op_eval_fbge,
743         gen_op_eval_fbuge,
744         gen_op_eval_fble,
745         gen_op_eval_fbule,
746         gen_op_eval_fbo,
747     },
748 #ifdef TARGET_SPARC64
749     {
750         gen_op_eval_bn,
751         gen_op_eval_fbne_fcc1,
752         gen_op_eval_fblg_fcc1,
753         gen_op_eval_fbul_fcc1,
754         gen_op_eval_fbl_fcc1,
755         gen_op_eval_fbug_fcc1,
756         gen_op_eval_fbg_fcc1,
757         gen_op_eval_fbu_fcc1,
758         gen_op_eval_ba,
759         gen_op_eval_fbe_fcc1,
760         gen_op_eval_fbue_fcc1,
761         gen_op_eval_fbge_fcc1,
762         gen_op_eval_fbuge_fcc1,
763         gen_op_eval_fble_fcc1,
764         gen_op_eval_fbule_fcc1,
765         gen_op_eval_fbo_fcc1,
766     },
767     {
768         gen_op_eval_bn,
769         gen_op_eval_fbne_fcc2,
770         gen_op_eval_fblg_fcc2,
771         gen_op_eval_fbul_fcc2,
772         gen_op_eval_fbl_fcc2,
773         gen_op_eval_fbug_fcc2,
774         gen_op_eval_fbg_fcc2,
775         gen_op_eval_fbu_fcc2,
776         gen_op_eval_ba,
777         gen_op_eval_fbe_fcc2,
778         gen_op_eval_fbue_fcc2,
779         gen_op_eval_fbge_fcc2,
780         gen_op_eval_fbuge_fcc2,
781         gen_op_eval_fble_fcc2,
782         gen_op_eval_fbule_fcc2,
783         gen_op_eval_fbo_fcc2,
784     },
785     {
786         gen_op_eval_bn,
787         gen_op_eval_fbne_fcc3,
788         gen_op_eval_fblg_fcc3,
789         gen_op_eval_fbul_fcc3,
790         gen_op_eval_fbl_fcc3,
791         gen_op_eval_fbug_fcc3,
792         gen_op_eval_fbg_fcc3,
793         gen_op_eval_fbu_fcc3,
794         gen_op_eval_ba,
795         gen_op_eval_fbe_fcc3,
796         gen_op_eval_fbue_fcc3,
797         gen_op_eval_fbge_fcc3,
798         gen_op_eval_fbuge_fcc3,
799         gen_op_eval_fble_fcc3,
800         gen_op_eval_fbule_fcc3,
801         gen_op_eval_fbo_fcc3,
802     },
803 #else
804     {}, {}, {},
805 #endif
806 };
807
808 #ifdef TARGET_SPARC64
809 static void gen_cond_reg(int cond)
810 {
811         switch (cond) {
812         case 0x1:
813             gen_op_eval_brz();
814             break;
815         case 0x2:
816             gen_op_eval_brlez();
817             break;
818         case 0x3:
819             gen_op_eval_brlz();
820             break;
821         case 0x5:
822             gen_op_eval_brnz();
823             break;
824         case 0x6:
825             gen_op_eval_brgz();
826             break;
827         default:
828         case 0x7:
829             gen_op_eval_brgez();
830             break;
831         }
832 }
833 #endif
834
835 /* XXX: potentially incorrect if dynamic npc */
836 static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
837 {
838     unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
839     target_ulong target = dc->pc + offset;
840         
841     if (cond == 0x0) {
842         /* unconditional not taken */
843         if (a) {
844             dc->pc = dc->npc + 4; 
845             dc->npc = dc->pc + 4;
846         } else {
847             dc->pc = dc->npc;
848             dc->npc = dc->pc + 4;
849         }
850     } else if (cond == 0x8) {
851         /* unconditional taken */
852         if (a) {
853             dc->pc = target;
854             dc->npc = dc->pc + 4;
855         } else {
856             dc->pc = dc->npc;
857             dc->npc = target;
858         }
859     } else {
860         flush_T2(dc);
861         gen_cond[cc][cond]();
862         if (a) {
863             gen_branch_a(dc, (long)dc->tb, target, dc->npc);
864             dc->is_br = 1;
865         } else {
866             dc->pc = dc->npc;
867             dc->jump_pc[0] = target;
868             dc->jump_pc[1] = dc->npc + 4;
869             dc->npc = JUMP_PC;
870         }
871     }
872 }
873
874 /* XXX: potentially incorrect if dynamic npc */
875 static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
876 {
877     unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
878     target_ulong target = dc->pc + offset;
879
880     if (cond == 0x0) {
881         /* unconditional not taken */
882         if (a) {
883             dc->pc = dc->npc + 4;
884             dc->npc = dc->pc + 4;
885         } else {
886             dc->pc = dc->npc;
887             dc->npc = dc->pc + 4;
888         }
889     } else if (cond == 0x8) {
890         /* unconditional taken */
891         if (a) {
892             dc->pc = target;
893             dc->npc = dc->pc + 4;
894         } else {
895             dc->pc = dc->npc;
896             dc->npc = target;
897         }
898     } else {
899         flush_T2(dc);
900         gen_fcond[cc][cond]();
901         if (a) {
902             gen_branch_a(dc, (long)dc->tb, target, dc->npc);
903             dc->is_br = 1;
904         } else {
905             dc->pc = dc->npc;
906             dc->jump_pc[0] = target;
907             dc->jump_pc[1] = dc->npc + 4;
908             dc->npc = JUMP_PC;
909         }
910     }
911 }
912
913 #ifdef TARGET_SPARC64
914 /* XXX: potentially incorrect if dynamic npc */
915 static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
916 {
917     unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
918     target_ulong target = dc->pc + offset;
919
920     flush_T2(dc);
921     gen_cond_reg(cond);
922     if (a) {
923         gen_branch_a(dc, (long)dc->tb, target, dc->npc);
924         dc->is_br = 1;
925     } else {
926         dc->pc = dc->npc;
927         dc->jump_pc[0] = target;
928         dc->jump_pc[1] = dc->npc + 4;
929         dc->npc = JUMP_PC;
930     }
931 }
932
933 static GenOpFunc * const gen_fcmps[4] = {
934     gen_op_fcmps,
935     gen_op_fcmps_fcc1,
936     gen_op_fcmps_fcc2,
937     gen_op_fcmps_fcc3,
938 };
939
940 static GenOpFunc * const gen_fcmpd[4] = {
941     gen_op_fcmpd,
942     gen_op_fcmpd_fcc1,
943     gen_op_fcmpd_fcc2,
944     gen_op_fcmpd_fcc3,
945 };
946 #endif
947
948 static int gen_trap_ifnofpu(DisasContext * dc)
949 {
950 #if !defined(CONFIG_USER_ONLY)
951     if (!dc->fpu_enabled) {
952         save_state(dc);
953         gen_op_exception(TT_NFPU_INSN);
954         dc->is_br = 1;
955         return 1;
956     }
957 #endif
958     return 0;
959 }
960
961 /* before an instruction, dc->pc must be static */
962 static void disas_sparc_insn(DisasContext * dc)
963 {
964     unsigned int insn, opc, rs1, rs2, rd;
965
966     insn = ldl_code(dc->pc);
967     opc = GET_FIELD(insn, 0, 1);
968
969     rd = GET_FIELD(insn, 2, 6);
970     switch (opc) {
971     case 0:                     /* branches/sethi */
972         {
973             unsigned int xop = GET_FIELD(insn, 7, 9);
974             int32_t target;
975             switch (xop) {
976 #ifdef TARGET_SPARC64
977             case 0x1:           /* V9 BPcc */
978                 {
979                     int cc;
980
981                     target = GET_FIELD_SP(insn, 0, 18);
982                     target = sign_extend(target, 18);
983                     target <<= 2;
984                     cc = GET_FIELD_SP(insn, 20, 21);
985                     if (cc == 0)
986                         do_branch(dc, target, insn, 0);
987                     else if (cc == 2)
988                         do_branch(dc, target, insn, 1);
989                     else
990                         goto illegal_insn;
991                     goto jmp_insn;
992                 }
993             case 0x3:           /* V9 BPr */
994                 {
995                     target = GET_FIELD_SP(insn, 0, 13) | 
996                         (GET_FIELD_SP(insn, 20, 21) << 14);
997                     target = sign_extend(target, 16);
998                     target <<= 2;
999                     rs1 = GET_FIELD(insn, 13, 17);
1000                     gen_movl_reg_T0(rs1);
1001                     do_branch_reg(dc, target, insn);
1002                     goto jmp_insn;
1003                 }
1004             case 0x5:           /* V9 FBPcc */
1005                 {
1006                     int cc = GET_FIELD_SP(insn, 20, 21);
1007                     if (gen_trap_ifnofpu(dc))
1008                         goto jmp_insn;
1009                     target = GET_FIELD_SP(insn, 0, 18);
1010                     target = sign_extend(target, 19);
1011                     target <<= 2;
1012                     do_fbranch(dc, target, insn, cc);
1013                     goto jmp_insn;
1014                 }
1015 #endif
1016             case 0x2:           /* BN+x */
1017                 {
1018                     target = GET_FIELD(insn, 10, 31);
1019                     target = sign_extend(target, 22);
1020                     target <<= 2;
1021                     do_branch(dc, target, insn, 0);
1022                     goto jmp_insn;
1023                 }
1024             case 0x6:           /* FBN+x */
1025                 {
1026                     if (gen_trap_ifnofpu(dc))
1027                         goto jmp_insn;
1028                     target = GET_FIELD(insn, 10, 31);
1029                     target = sign_extend(target, 22);
1030                     target <<= 2;
1031                     do_fbranch(dc, target, insn, 0);
1032                     goto jmp_insn;
1033                 }
1034             case 0x4:           /* SETHI */
1035 #define OPTIM
1036 #if defined(OPTIM)
1037                 if (rd) { // nop
1038 #endif
1039                     uint32_t value = GET_FIELD(insn, 10, 31);
1040                     gen_movl_imm_T0(value << 10);
1041                     gen_movl_T0_reg(rd);
1042 #if defined(OPTIM)
1043                 }
1044 #endif
1045                 break;
1046             case 0x0:           /* UNIMPL */
1047             default:
1048                 goto illegal_insn;
1049             }
1050             break;
1051         }
1052         break;
1053     case 1:
1054         /*CALL*/ {
1055             target_long target = GET_FIELDs(insn, 2, 31) << 2;
1056
1057 #ifdef TARGET_SPARC64
1058             if (dc->pc == (uint32_t)dc->pc) {
1059                 gen_op_movl_T0_im(dc->pc);
1060             } else {
1061                 gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1062             }
1063 #else
1064             gen_op_movl_T0_im(dc->pc);
1065 #endif
1066             gen_movl_T0_reg(15);
1067             target += dc->pc;
1068             gen_mov_pc_npc(dc);
1069             dc->npc = target;
1070         }
1071         goto jmp_insn;
1072     case 2:                     /* FPU & Logical Operations */
1073         {
1074             unsigned int xop = GET_FIELD(insn, 7, 12);
1075             if (xop == 0x3a) {  /* generate trap */
1076                 int cond;
1077
1078                 rs1 = GET_FIELD(insn, 13, 17);
1079                 gen_movl_reg_T0(rs1);
1080                 if (IS_IMM) {
1081                     rs2 = GET_FIELD(insn, 25, 31);
1082 #if defined(OPTIM)
1083                     if (rs2 != 0) {
1084 #endif
1085                         gen_movl_simm_T1(rs2);
1086                         gen_op_add_T1_T0();
1087 #if defined(OPTIM)
1088                     }
1089 #endif
1090                 } else {
1091                     rs2 = GET_FIELD(insn, 27, 31);
1092 #if defined(OPTIM)
1093                     if (rs2 != 0) {
1094 #endif
1095                         gen_movl_reg_T1(rs2);
1096                         gen_op_add_T1_T0();
1097 #if defined(OPTIM)
1098                     }
1099 #endif
1100                 }
1101                 cond = GET_FIELD(insn, 3, 6);
1102                 if (cond == 0x8) {
1103                     save_state(dc);
1104                     gen_op_trap_T0();
1105                 } else if (cond != 0) {
1106 #ifdef TARGET_SPARC64
1107                     /* V9 icc/xcc */
1108                     int cc = GET_FIELD_SP(insn, 11, 12);
1109                     flush_T2(dc);
1110                     save_state(dc);
1111                     if (cc == 0)
1112                         gen_cond[0][cond]();
1113                     else if (cc == 2)
1114                         gen_cond[1][cond]();
1115                     else
1116                         goto illegal_insn;
1117 #else
1118                     flush_T2(dc);
1119                     save_state(dc);
1120                     gen_cond[0][cond]();
1121 #endif
1122                     gen_op_trapcc_T0();
1123                 }
1124                 gen_op_next_insn();
1125                 gen_op_movl_T0_0();
1126                 gen_op_exit_tb();
1127                 dc->is_br = 1;
1128                 goto jmp_insn;
1129             } else if (xop == 0x28) {
1130                 rs1 = GET_FIELD(insn, 13, 17);
1131                 switch(rs1) {
1132                 case 0: /* rdy */
1133                     gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
1134                     gen_movl_T0_reg(rd);
1135                     break;
1136                 case 15: /* stbar / V9 membar */
1137                     break; /* no effect? */
1138 #ifdef TARGET_SPARC64
1139                 case 0x2: /* V9 rdccr */
1140                     gen_op_rdccr();
1141                     gen_movl_T0_reg(rd);
1142                     break;
1143                 case 0x3: /* V9 rdasi */
1144                     gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
1145                     gen_movl_T0_reg(rd);
1146                     break;
1147                 case 0x4: /* V9 rdtick */
1148                     gen_op_rdtick();
1149                     gen_movl_T0_reg(rd);
1150                     break;
1151                 case 0x5: /* V9 rdpc */
1152                     if (dc->pc == (uint32_t)dc->pc) {
1153                         gen_op_movl_T0_im(dc->pc);
1154                     } else {
1155                         gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1156                     }
1157                     gen_movl_T0_reg(rd);
1158                     break;
1159                 case 0x6: /* V9 rdfprs */
1160                     gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
1161                     gen_movl_T0_reg(rd);
1162                     break;
1163                 case 0x13: /* Graphics Status */
1164                     if (gen_trap_ifnofpu(dc))
1165                         goto jmp_insn;
1166                     gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
1167                     gen_movl_T0_reg(rd);
1168                     break;
1169                 case 0x17: /* Tick compare */
1170                     gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
1171                     gen_movl_T0_reg(rd);
1172                     break;
1173                 case 0x18: /* System tick */
1174                     gen_op_rdtick(); // XXX
1175                     gen_movl_T0_reg(rd);
1176                     break;
1177                 case 0x19: /* System tick compare */
1178                     gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
1179                     gen_movl_T0_reg(rd);
1180                     break;
1181                 case 0x10: /* Performance Control */
1182                 case 0x11: /* Performance Instrumentation Counter */
1183                 case 0x12: /* Dispatch Control */
1184                 case 0x14: /* Softint set, WO */
1185                 case 0x15: /* Softint clear, WO */
1186                 case 0x16: /* Softint write */
1187 #endif
1188                 default:
1189                     goto illegal_insn;
1190                 }
1191 #if !defined(CONFIG_USER_ONLY)
1192 #ifndef TARGET_SPARC64
1193             } else if (xop == 0x29) { /* rdpsr / V9 unimp */
1194                 if (!supervisor(dc))
1195                     goto priv_insn;
1196                 gen_op_rdpsr();
1197                 gen_movl_T0_reg(rd);
1198                 break;
1199 #endif
1200             } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1201                 if (!supervisor(dc))
1202                     goto priv_insn;
1203 #ifdef TARGET_SPARC64
1204                 rs1 = GET_FIELD(insn, 13, 17);
1205                 switch (rs1) {
1206                 case 0: // tpc
1207                     gen_op_rdtpc();
1208                     break;
1209                 case 1: // tnpc
1210                     gen_op_rdtnpc();
1211                     break;
1212                 case 2: // tstate
1213                     gen_op_rdtstate();
1214                     break;
1215                 case 3: // tt
1216                     gen_op_rdtt();
1217                     break;
1218                 case 4: // tick
1219                     gen_op_rdtick();
1220                     break;
1221                 case 5: // tba
1222                     gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1223                     break;
1224                 case 6: // pstate
1225                     gen_op_rdpstate();
1226                     break;
1227                 case 7: // tl
1228                     gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
1229                     break;
1230                 case 8: // pil
1231                     gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
1232                     break;
1233                 case 9: // cwp
1234                     gen_op_rdcwp();
1235                     break;
1236                 case 10: // cansave
1237                     gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
1238                     break;
1239                 case 11: // canrestore
1240                     gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
1241                     break;
1242                 case 12: // cleanwin
1243                     gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
1244                     break;
1245                 case 13: // otherwin
1246                     gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
1247                     break;
1248                 case 14: // wstate
1249                     gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
1250                     break;
1251                 case 31: // ver
1252                     gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
1253                     break;
1254                 case 15: // fq
1255                 default:
1256                     goto illegal_insn;
1257                 }
1258 #else
1259                 gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
1260 #endif
1261                 gen_movl_T0_reg(rd);
1262                 break;
1263             } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
1264 #ifdef TARGET_SPARC64
1265                 gen_op_flushw();
1266 #else
1267                 if (!supervisor(dc))
1268                     goto priv_insn;
1269                 gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1270                 gen_movl_T0_reg(rd);
1271 #endif
1272                 break;
1273 #endif
1274             } else if (xop == 0x34) {   /* FPU Operations */
1275                 if (gen_trap_ifnofpu(dc))
1276                     goto jmp_insn;
1277                 rs1 = GET_FIELD(insn, 13, 17);
1278                 rs2 = GET_FIELD(insn, 27, 31);
1279                 xop = GET_FIELD(insn, 18, 26);
1280                 switch (xop) {
1281                     case 0x1: /* fmovs */
1282                         gen_op_load_fpr_FT0(rs2);
1283                         gen_op_store_FT0_fpr(rd);
1284                         break;
1285                     case 0x5: /* fnegs */
1286                         gen_op_load_fpr_FT1(rs2);
1287                         gen_op_fnegs();
1288                         gen_op_store_FT0_fpr(rd);
1289                         break;
1290                     case 0x9: /* fabss */
1291                         gen_op_load_fpr_FT1(rs2);
1292                         gen_op_fabss();
1293                         gen_op_store_FT0_fpr(rd);
1294                         break;
1295                     case 0x29: /* fsqrts */
1296                         gen_op_load_fpr_FT1(rs2);
1297                         gen_op_fsqrts();
1298                         gen_op_store_FT0_fpr(rd);
1299                         break;
1300                     case 0x2a: /* fsqrtd */
1301                         gen_op_load_fpr_DT1(DFPREG(rs2));
1302                         gen_op_fsqrtd();
1303                         gen_op_store_DT0_fpr(DFPREG(rd));
1304                         break;
1305                     case 0x2b: /* fsqrtq */
1306                         goto nfpu_insn;
1307                     case 0x41:
1308                         gen_op_load_fpr_FT0(rs1);
1309                         gen_op_load_fpr_FT1(rs2);
1310                         gen_op_fadds();
1311                         gen_op_store_FT0_fpr(rd);
1312                         break;
1313                     case 0x42:
1314                         gen_op_load_fpr_DT0(DFPREG(rs1));
1315                         gen_op_load_fpr_DT1(DFPREG(rs2));
1316                         gen_op_faddd();
1317                         gen_op_store_DT0_fpr(DFPREG(rd));
1318                         break;
1319                     case 0x43: /* faddq */
1320                         goto nfpu_insn;
1321                     case 0x45:
1322                         gen_op_load_fpr_FT0(rs1);
1323                         gen_op_load_fpr_FT1(rs2);
1324                         gen_op_fsubs();
1325                         gen_op_store_FT0_fpr(rd);
1326                         break;
1327                     case 0x46:
1328                         gen_op_load_fpr_DT0(DFPREG(rs1));
1329                         gen_op_load_fpr_DT1(DFPREG(rs2));
1330                         gen_op_fsubd();
1331                         gen_op_store_DT0_fpr(DFPREG(rd));
1332                         break;
1333                     case 0x47: /* fsubq */
1334                         goto nfpu_insn;
1335                     case 0x49:
1336                         gen_op_load_fpr_FT0(rs1);
1337                         gen_op_load_fpr_FT1(rs2);
1338                         gen_op_fmuls();
1339                         gen_op_store_FT0_fpr(rd);
1340                         break;
1341                     case 0x4a:
1342                         gen_op_load_fpr_DT0(DFPREG(rs1));
1343                         gen_op_load_fpr_DT1(DFPREG(rs2));
1344                         gen_op_fmuld();
1345                         gen_op_store_DT0_fpr(rd);
1346                         break;
1347                     case 0x4b: /* fmulq */
1348                         goto nfpu_insn;
1349                     case 0x4d:
1350                         gen_op_load_fpr_FT0(rs1);
1351                         gen_op_load_fpr_FT1(rs2);
1352                         gen_op_fdivs();
1353                         gen_op_store_FT0_fpr(rd);
1354                         break;
1355                     case 0x4e:
1356                         gen_op_load_fpr_DT0(DFPREG(rs1));
1357                         gen_op_load_fpr_DT1(DFPREG(rs2));
1358                         gen_op_fdivd();
1359                         gen_op_store_DT0_fpr(DFPREG(rd));
1360                         break;
1361                     case 0x4f: /* fdivq */
1362                         goto nfpu_insn;
1363                     case 0x69:
1364                         gen_op_load_fpr_FT0(rs1);
1365                         gen_op_load_fpr_FT1(rs2);
1366                         gen_op_fsmuld();
1367                         gen_op_store_DT0_fpr(DFPREG(rd));
1368                         break;
1369                     case 0x6e: /* fdmulq */
1370                         goto nfpu_insn;
1371                     case 0xc4:
1372                         gen_op_load_fpr_FT1(rs2);
1373                         gen_op_fitos();
1374                         gen_op_store_FT0_fpr(rd);
1375                         break;
1376                     case 0xc6:
1377                         gen_op_load_fpr_DT1(DFPREG(rs2));
1378                         gen_op_fdtos();
1379                         gen_op_store_FT0_fpr(rd);
1380                         break;
1381                     case 0xc7: /* fqtos */
1382                         goto nfpu_insn;
1383                     case 0xc8:
1384                         gen_op_load_fpr_FT1(rs2);
1385                         gen_op_fitod();
1386                         gen_op_store_DT0_fpr(DFPREG(rd));
1387                         break;
1388                     case 0xc9:
1389                         gen_op_load_fpr_FT1(rs2);
1390                         gen_op_fstod();
1391                         gen_op_store_DT0_fpr(DFPREG(rd));
1392                         break;
1393                     case 0xcb: /* fqtod */
1394                         goto nfpu_insn;
1395                     case 0xcc: /* fitoq */
1396                         goto nfpu_insn;
1397                     case 0xcd: /* fstoq */
1398                         goto nfpu_insn;
1399                     case 0xce: /* fdtoq */
1400                         goto nfpu_insn;
1401                     case 0xd1:
1402                         gen_op_load_fpr_FT1(rs2);
1403                         gen_op_fstoi();
1404                         gen_op_store_FT0_fpr(rd);
1405                         break;
1406                     case 0xd2:
1407                         gen_op_load_fpr_DT1(rs2);
1408                         gen_op_fdtoi();
1409                         gen_op_store_FT0_fpr(rd);
1410                         break;
1411                     case 0xd3: /* fqtoi */
1412                         goto nfpu_insn;
1413 #ifdef TARGET_SPARC64
1414                     case 0x2: /* V9 fmovd */
1415                         gen_op_load_fpr_DT0(DFPREG(rs2));
1416                         gen_op_store_DT0_fpr(DFPREG(rd));
1417                         break;
1418                     case 0x6: /* V9 fnegd */
1419                         gen_op_load_fpr_DT1(DFPREG(rs2));
1420                         gen_op_fnegd();
1421                         gen_op_store_DT0_fpr(DFPREG(rd));
1422                         break;
1423                     case 0xa: /* V9 fabsd */
1424                         gen_op_load_fpr_DT1(DFPREG(rs2));
1425                         gen_op_fabsd();
1426                         gen_op_store_DT0_fpr(DFPREG(rd));
1427                         break;
1428                     case 0x81: /* V9 fstox */
1429                         gen_op_load_fpr_FT1(rs2);
1430                         gen_op_fstox();
1431                         gen_op_store_DT0_fpr(DFPREG(rd));
1432                         break;
1433                     case 0x82: /* V9 fdtox */
1434                         gen_op_load_fpr_DT1(DFPREG(rs2));
1435                         gen_op_fdtox();
1436                         gen_op_store_DT0_fpr(DFPREG(rd));
1437                         break;
1438                     case 0x84: /* V9 fxtos */
1439                         gen_op_load_fpr_DT1(DFPREG(rs2));
1440                         gen_op_fxtos();
1441                         gen_op_store_FT0_fpr(rd);
1442                         break;
1443                     case 0x88: /* V9 fxtod */
1444                         gen_op_load_fpr_DT1(DFPREG(rs2));
1445                         gen_op_fxtod();
1446                         gen_op_store_DT0_fpr(DFPREG(rd));
1447                         break;
1448                     case 0x3: /* V9 fmovq */
1449                     case 0x7: /* V9 fnegq */
1450                     case 0xb: /* V9 fabsq */
1451                     case 0x83: /* V9 fqtox */
1452                     case 0x8c: /* V9 fxtoq */
1453                         goto nfpu_insn;
1454 #endif
1455                     default:
1456                         goto illegal_insn;
1457                 }
1458             } else if (xop == 0x35) {   /* FPU Operations */
1459 #ifdef TARGET_SPARC64
1460                 int cond;
1461 #endif
1462                 if (gen_trap_ifnofpu(dc))
1463                     goto jmp_insn;
1464                 rs1 = GET_FIELD(insn, 13, 17);
1465                 rs2 = GET_FIELD(insn, 27, 31);
1466                 xop = GET_FIELD(insn, 18, 26);
1467 #ifdef TARGET_SPARC64
1468                 if ((xop & 0x11f) == 0x005) { // V9 fmovsr
1469                     cond = GET_FIELD_SP(insn, 14, 17);
1470                     gen_op_load_fpr_FT0(rd);
1471                     gen_op_load_fpr_FT1(rs2);
1472                     rs1 = GET_FIELD(insn, 13, 17);
1473                     gen_movl_reg_T0(rs1);
1474                     flush_T2(dc);
1475                     gen_cond_reg(cond);
1476                     gen_op_fmovs_cc();
1477                     gen_op_store_FT0_fpr(rd);
1478                     break;
1479                 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
1480                     cond = GET_FIELD_SP(insn, 14, 17);
1481                     gen_op_load_fpr_DT0(rd);
1482                     gen_op_load_fpr_DT1(rs2);
1483                     flush_T2(dc);
1484                     rs1 = GET_FIELD(insn, 13, 17);
1485                     gen_movl_reg_T0(rs1);
1486                     gen_cond_reg(cond);
1487                     gen_op_fmovs_cc();
1488                     gen_op_store_DT0_fpr(rd);
1489                     break;
1490                 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
1491                     goto nfpu_insn;
1492                 }
1493 #endif
1494                 switch (xop) {
1495 #ifdef TARGET_SPARC64
1496                     case 0x001: /* V9 fmovscc %fcc0 */
1497                         cond = GET_FIELD_SP(insn, 14, 17);
1498                         gen_op_load_fpr_FT0(rd);
1499                         gen_op_load_fpr_FT1(rs2);
1500                         flush_T2(dc);
1501                         gen_fcond[0][cond]();
1502                         gen_op_fmovs_cc();
1503                         gen_op_store_FT0_fpr(rd);
1504                         break;
1505                     case 0x002: /* V9 fmovdcc %fcc0 */
1506                         cond = GET_FIELD_SP(insn, 14, 17);
1507                         gen_op_load_fpr_DT0(rd);
1508                         gen_op_load_fpr_DT1(rs2);
1509                         flush_T2(dc);
1510                         gen_fcond[0][cond]();
1511                         gen_op_fmovd_cc();
1512                         gen_op_store_DT0_fpr(rd);
1513                         break;
1514                     case 0x003: /* V9 fmovqcc %fcc0 */
1515                         goto nfpu_insn;
1516                     case 0x041: /* V9 fmovscc %fcc1 */
1517                         cond = GET_FIELD_SP(insn, 14, 17);
1518                         gen_op_load_fpr_FT0(rd);
1519                         gen_op_load_fpr_FT1(rs2);
1520                         flush_T2(dc);
1521                         gen_fcond[1][cond]();
1522                         gen_op_fmovs_cc();
1523                         gen_op_store_FT0_fpr(rd);
1524                         break;
1525                     case 0x042: /* V9 fmovdcc %fcc1 */
1526                         cond = GET_FIELD_SP(insn, 14, 17);
1527                         gen_op_load_fpr_DT0(rd);
1528                         gen_op_load_fpr_DT1(rs2);
1529                         flush_T2(dc);
1530                         gen_fcond[1][cond]();
1531                         gen_op_fmovd_cc();
1532                         gen_op_store_DT0_fpr(rd);
1533                         break;
1534                     case 0x043: /* V9 fmovqcc %fcc1 */
1535                         goto nfpu_insn;
1536                     case 0x081: /* V9 fmovscc %fcc2 */
1537                         cond = GET_FIELD_SP(insn, 14, 17);
1538                         gen_op_load_fpr_FT0(rd);
1539                         gen_op_load_fpr_FT1(rs2);
1540                         flush_T2(dc);
1541                         gen_fcond[2][cond]();
1542                         gen_op_fmovs_cc();
1543                         gen_op_store_FT0_fpr(rd);
1544                         break;
1545                     case 0x082: /* V9 fmovdcc %fcc2 */
1546                         cond = GET_FIELD_SP(insn, 14, 17);
1547                         gen_op_load_fpr_DT0(rd);
1548                         gen_op_load_fpr_DT1(rs2);
1549                         flush_T2(dc);
1550                         gen_fcond[2][cond]();
1551                         gen_op_fmovd_cc();
1552                         gen_op_store_DT0_fpr(rd);
1553                         break;
1554                     case 0x083: /* V9 fmovqcc %fcc2 */
1555                         goto nfpu_insn;
1556                     case 0x0c1: /* V9 fmovscc %fcc3 */
1557                         cond = GET_FIELD_SP(insn, 14, 17);
1558                         gen_op_load_fpr_FT0(rd);
1559                         gen_op_load_fpr_FT1(rs2);
1560                         flush_T2(dc);
1561                         gen_fcond[3][cond]();
1562                         gen_op_fmovs_cc();
1563                         gen_op_store_FT0_fpr(rd);
1564                         break;
1565                     case 0x0c2: /* V9 fmovdcc %fcc3 */
1566                         cond = GET_FIELD_SP(insn, 14, 17);
1567                         gen_op_load_fpr_DT0(rd);
1568                         gen_op_load_fpr_DT1(rs2);
1569                         flush_T2(dc);
1570                         gen_fcond[3][cond]();
1571                         gen_op_fmovd_cc();
1572                         gen_op_store_DT0_fpr(rd);
1573                         break;
1574                     case 0x0c3: /* V9 fmovqcc %fcc3 */
1575                         goto nfpu_insn;
1576                     case 0x101: /* V9 fmovscc %icc */
1577                         cond = GET_FIELD_SP(insn, 14, 17);
1578                         gen_op_load_fpr_FT0(rd);
1579                         gen_op_load_fpr_FT1(rs2);
1580                         flush_T2(dc);
1581                         gen_cond[0][cond]();
1582                         gen_op_fmovs_cc();
1583                         gen_op_store_FT0_fpr(rd);
1584                         break;
1585                     case 0x102: /* V9 fmovdcc %icc */
1586                         cond = GET_FIELD_SP(insn, 14, 17);
1587                         gen_op_load_fpr_DT0(rd);
1588                         gen_op_load_fpr_DT1(rs2);
1589                         flush_T2(dc);
1590                         gen_cond[0][cond]();
1591                         gen_op_fmovd_cc();
1592                         gen_op_store_DT0_fpr(rd);
1593                         break;
1594                     case 0x103: /* V9 fmovqcc %icc */
1595                         goto nfpu_insn;
1596                     case 0x181: /* V9 fmovscc %xcc */
1597                         cond = GET_FIELD_SP(insn, 14, 17);
1598                         gen_op_load_fpr_FT0(rd);
1599                         gen_op_load_fpr_FT1(rs2);
1600                         flush_T2(dc);
1601                         gen_cond[1][cond]();
1602                         gen_op_fmovs_cc();
1603                         gen_op_store_FT0_fpr(rd);
1604                         break;
1605                     case 0x182: /* V9 fmovdcc %xcc */
1606                         cond = GET_FIELD_SP(insn, 14, 17);
1607                         gen_op_load_fpr_DT0(rd);
1608                         gen_op_load_fpr_DT1(rs2);
1609                         flush_T2(dc);
1610                         gen_cond[1][cond]();
1611                         gen_op_fmovd_cc();
1612                         gen_op_store_DT0_fpr(rd);
1613                         break;
1614                     case 0x183: /* V9 fmovqcc %xcc */
1615                         goto nfpu_insn;
1616 #endif
1617                     case 0x51: /* V9 %fcc */
1618                         gen_op_load_fpr_FT0(rs1);
1619                         gen_op_load_fpr_FT1(rs2);
1620 #ifdef TARGET_SPARC64
1621                         gen_fcmps[rd & 3]();
1622 #else
1623                         gen_op_fcmps();
1624 #endif
1625                         break;
1626                     case 0x52: /* V9 %fcc */
1627                         gen_op_load_fpr_DT0(DFPREG(rs1));
1628                         gen_op_load_fpr_DT1(DFPREG(rs2));
1629 #ifdef TARGET_SPARC64
1630                         gen_fcmpd[rd & 3]();
1631 #else
1632                         gen_op_fcmpd();
1633 #endif
1634                         break;
1635                     case 0x53: /* fcmpq */
1636                         goto nfpu_insn;
1637                     case 0x55: /* fcmpes, V9 %fcc */
1638                         gen_op_load_fpr_FT0(rs1);
1639                         gen_op_load_fpr_FT1(rs2);
1640 #ifdef TARGET_SPARC64
1641                         gen_fcmps[rd & 3]();
1642 #else
1643                         gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */
1644 #endif
1645                         break;
1646                     case 0x56: /* fcmped, V9 %fcc */
1647                         gen_op_load_fpr_DT0(DFPREG(rs1));
1648                         gen_op_load_fpr_DT1(DFPREG(rs2));
1649 #ifdef TARGET_SPARC64
1650                         gen_fcmpd[rd & 3]();
1651 #else
1652                         gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */
1653 #endif
1654                         break;
1655                     case 0x57: /* fcmpeq */
1656                         goto nfpu_insn;
1657                     default:
1658                         goto illegal_insn;
1659                 }
1660 #if defined(OPTIM)
1661             } else if (xop == 0x2) {
1662                 // clr/mov shortcut
1663
1664                 rs1 = GET_FIELD(insn, 13, 17);
1665                 if (rs1 == 0) {
1666                     // or %g0, x, y -> mov T1, x; mov y, T1
1667                     if (IS_IMM) {       /* immediate */
1668                         rs2 = GET_FIELDs(insn, 19, 31);
1669                         gen_movl_simm_T1(rs2);
1670                     } else {            /* register */
1671                         rs2 = GET_FIELD(insn, 27, 31);
1672                         gen_movl_reg_T1(rs2);
1673                     }
1674                     gen_movl_T1_reg(rd);
1675                 } else {
1676                     gen_movl_reg_T0(rs1);
1677                     if (IS_IMM) {       /* immediate */
1678                         // or x, #0, y -> mov T1, x; mov y, T1
1679                         rs2 = GET_FIELDs(insn, 19, 31);
1680                         if (rs2 != 0) {
1681                             gen_movl_simm_T1(rs2);
1682                             gen_op_or_T1_T0();
1683                         }
1684                     } else {            /* register */
1685                         // or x, %g0, y -> mov T1, x; mov y, T1
1686                         rs2 = GET_FIELD(insn, 27, 31);
1687                         if (rs2 != 0) {
1688                             gen_movl_reg_T1(rs2);
1689                             gen_op_or_T1_T0();
1690                         }
1691                     }
1692                     gen_movl_T0_reg(rd);
1693                 }
1694 #endif
1695 #ifdef TARGET_SPARC64
1696             } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */
1697                 rs1 = GET_FIELD(insn, 13, 17);
1698                 gen_movl_reg_T0(rs1);
1699                 if (IS_IMM) {   /* immediate */
1700                     rs2 = GET_FIELDs(insn, 20, 31);
1701                     gen_movl_simm_T1(rs2);
1702                 } else {                /* register */
1703                     rs2 = GET_FIELD(insn, 27, 31);
1704                     gen_movl_reg_T1(rs2);
1705                 }
1706                 gen_op_sll();
1707                 gen_movl_T0_reg(rd);
1708             } else if (xop == 0x26) { /* srl, V9 srlx */
1709                 rs1 = GET_FIELD(insn, 13, 17);
1710                 gen_movl_reg_T0(rs1);
1711                 if (IS_IMM) {   /* immediate */
1712                     rs2 = GET_FIELDs(insn, 20, 31);
1713                     gen_movl_simm_T1(rs2);
1714                 } else {                /* register */
1715                     rs2 = GET_FIELD(insn, 27, 31);
1716                     gen_movl_reg_T1(rs2);
1717                 }
1718                 if (insn & (1 << 12))
1719                     gen_op_srlx();
1720                 else
1721                     gen_op_srl();
1722                 gen_movl_T0_reg(rd);
1723             } else if (xop == 0x27) { /* sra, V9 srax */
1724                 rs1 = GET_FIELD(insn, 13, 17);
1725                 gen_movl_reg_T0(rs1);
1726                 if (IS_IMM) {   /* immediate */
1727                     rs2 = GET_FIELDs(insn, 20, 31);
1728                     gen_movl_simm_T1(rs2);
1729                 } else {                /* register */
1730                     rs2 = GET_FIELD(insn, 27, 31);
1731                     gen_movl_reg_T1(rs2);
1732                 }
1733                 if (insn & (1 << 12))
1734                     gen_op_srax();
1735                 else
1736                     gen_op_sra();
1737                 gen_movl_T0_reg(rd);
1738 #endif
1739             } else if (xop < 0x38) {
1740                 rs1 = GET_FIELD(insn, 13, 17);
1741                 gen_movl_reg_T0(rs1);
1742                 if (IS_IMM) {   /* immediate */
1743                     rs2 = GET_FIELDs(insn, 19, 31);
1744                     gen_movl_simm_T1(rs2);
1745                 } else {                /* register */
1746                     rs2 = GET_FIELD(insn, 27, 31);
1747                     gen_movl_reg_T1(rs2);
1748                 }
1749                 if (xop < 0x20) {
1750                     switch (xop & ~0x10) {
1751                     case 0x0:
1752                         if (xop & 0x10)
1753                             gen_op_add_T1_T0_cc();
1754                         else
1755                             gen_op_add_T1_T0();
1756                         break;
1757                     case 0x1:
1758                         gen_op_and_T1_T0();
1759                         if (xop & 0x10)
1760                             gen_op_logic_T0_cc();
1761                         break;
1762                     case 0x2:
1763                         gen_op_or_T1_T0();
1764                         if (xop & 0x10)
1765                             gen_op_logic_T0_cc();
1766                         break;
1767                     case 0x3:
1768                         gen_op_xor_T1_T0();
1769                         if (xop & 0x10)
1770                             gen_op_logic_T0_cc();
1771                         break;
1772                     case 0x4:
1773                         if (xop & 0x10)
1774                             gen_op_sub_T1_T0_cc();
1775                         else
1776                             gen_op_sub_T1_T0();
1777                         break;
1778                     case 0x5:
1779                         gen_op_andn_T1_T0();
1780                         if (xop & 0x10)
1781                             gen_op_logic_T0_cc();
1782                         break;
1783                     case 0x6:
1784                         gen_op_orn_T1_T0();
1785                         if (xop & 0x10)
1786                             gen_op_logic_T0_cc();
1787                         break;
1788                     case 0x7:
1789                         gen_op_xnor_T1_T0();
1790                         if (xop & 0x10)
1791                             gen_op_logic_T0_cc();
1792                         break;
1793                     case 0x8:
1794                         if (xop & 0x10)
1795                             gen_op_addx_T1_T0_cc();
1796                         else
1797                             gen_op_addx_T1_T0();
1798                         break;
1799 #ifdef TARGET_SPARC64
1800                     case 0x9: /* V9 mulx */
1801                         gen_op_mulx_T1_T0();
1802                         break;
1803 #endif
1804                     case 0xa:
1805                         gen_op_umul_T1_T0();
1806                         if (xop & 0x10)
1807                             gen_op_logic_T0_cc();
1808                         break;
1809                     case 0xb:
1810                         gen_op_smul_T1_T0();
1811                         if (xop & 0x10)
1812                             gen_op_logic_T0_cc();
1813                         break;
1814                     case 0xc:
1815                         if (xop & 0x10)
1816                             gen_op_subx_T1_T0_cc();
1817                         else
1818                             gen_op_subx_T1_T0();
1819                         break;
1820 #ifdef TARGET_SPARC64
1821                     case 0xd: /* V9 udivx */
1822                         gen_op_udivx_T1_T0();
1823                         break;
1824 #endif
1825                     case 0xe:
1826                         gen_op_udiv_T1_T0();
1827                         if (xop & 0x10)
1828                             gen_op_div_cc();
1829                         break;
1830                     case 0xf:
1831                         gen_op_sdiv_T1_T0();
1832                         if (xop & 0x10)
1833                             gen_op_div_cc();
1834                         break;
1835                     default:
1836                         goto illegal_insn;
1837                     }
1838                     gen_movl_T0_reg(rd);
1839                 } else {
1840                     switch (xop) {
1841                     case 0x20: /* taddcc */
1842                         gen_op_tadd_T1_T0_cc();
1843                         gen_movl_T0_reg(rd);
1844                         break;
1845                     case 0x21: /* tsubcc */
1846                         gen_op_tsub_T1_T0_cc();
1847                         gen_movl_T0_reg(rd);
1848                         break;
1849                     case 0x22: /* taddcctv */
1850                         gen_op_tadd_T1_T0_ccTV();
1851                         gen_movl_T0_reg(rd);
1852                         break;
1853                     case 0x23: /* tsubcctv */
1854                         gen_op_tsub_T1_T0_ccTV();
1855                         gen_movl_T0_reg(rd);
1856                         break;
1857                     case 0x24: /* mulscc */
1858                         gen_op_mulscc_T1_T0();
1859                         gen_movl_T0_reg(rd);
1860                         break;
1861 #ifndef TARGET_SPARC64
1862                     case 0x25:  /* sll */
1863                         gen_op_sll();
1864                         gen_movl_T0_reg(rd);
1865                         break;
1866                     case 0x26:  /* srl */
1867                         gen_op_srl();
1868                         gen_movl_T0_reg(rd);
1869                         break;
1870                     case 0x27:  /* sra */
1871                         gen_op_sra();
1872                         gen_movl_T0_reg(rd);
1873                         break;
1874 #endif
1875                     case 0x30:
1876                         {
1877                             switch(rd) {
1878                             case 0: /* wry */
1879                                 gen_op_xor_T1_T0();
1880                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1881                                 break;
1882 #ifdef TARGET_SPARC64
1883                             case 0x2: /* V9 wrccr */
1884                                 gen_op_wrccr();
1885                                 break;
1886                             case 0x3: /* V9 wrasi */
1887                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
1888                                 break;
1889                             case 0x6: /* V9 wrfprs */
1890                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
1891                                 break;
1892                             case 0xf: /* V9 sir, nop if user */
1893 #if !defined(CONFIG_USER_ONLY)
1894                                 if (supervisor(dc))
1895                                     gen_op_sir();
1896 #endif
1897                                 break;
1898                             case 0x13: /* Graphics Status */
1899                                 if (gen_trap_ifnofpu(dc))
1900                                     goto jmp_insn;
1901                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
1902                                 break;
1903                             case 0x17: /* Tick compare */
1904 #if !defined(CONFIG_USER_ONLY)
1905                                 if (!supervisor(dc))
1906                                     goto illegal_insn;
1907 #endif
1908                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
1909                                 break;
1910                             case 0x18: /* System tick */
1911 #if !defined(CONFIG_USER_ONLY)
1912                                 if (!supervisor(dc))
1913                                     goto illegal_insn;
1914 #endif
1915                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
1916                                 break;
1917                             case 0x19: /* System tick compare */
1918 #if !defined(CONFIG_USER_ONLY)
1919                                 if (!supervisor(dc))
1920                                     goto illegal_insn;
1921 #endif
1922                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
1923                                 break;
1924
1925                             case 0x10: /* Performance Control */
1926                             case 0x11: /* Performance Instrumentation Counter */
1927                             case 0x12: /* Dispatch Control */
1928                             case 0x14: /* Softint set */
1929                             case 0x15: /* Softint clear */
1930                             case 0x16: /* Softint write */
1931 #endif
1932                             default:
1933                                 goto illegal_insn;
1934                             }
1935                         }
1936                         break;
1937 #if !defined(CONFIG_USER_ONLY)
1938                     case 0x31: /* wrpsr, V9 saved, restored */
1939                         {
1940                             if (!supervisor(dc))
1941                                 goto priv_insn;
1942 #ifdef TARGET_SPARC64
1943                             switch (rd) {
1944                             case 0:
1945                                 gen_op_saved();
1946                                 break;
1947                             case 1:
1948                                 gen_op_restored();
1949                                 break;
1950                             default:
1951                                 goto illegal_insn;
1952                             }
1953 #else
1954                             gen_op_xor_T1_T0();
1955                             gen_op_wrpsr();
1956                             save_state(dc);
1957                             gen_op_next_insn();
1958                             gen_op_movl_T0_0();
1959                             gen_op_exit_tb();
1960                             dc->is_br = 1;
1961 #endif
1962                         }
1963                         break;
1964                     case 0x32: /* wrwim, V9 wrpr */
1965                         {
1966                             if (!supervisor(dc))
1967                                 goto priv_insn;
1968                             gen_op_xor_T1_T0();
1969 #ifdef TARGET_SPARC64
1970                             switch (rd) {
1971                             case 0: // tpc
1972                                 gen_op_wrtpc();
1973                                 break;
1974                             case 1: // tnpc
1975                                 gen_op_wrtnpc();
1976                                 break;
1977                             case 2: // tstate
1978                                 gen_op_wrtstate();
1979                                 break;
1980                             case 3: // tt
1981                                 gen_op_wrtt();
1982                                 break;
1983                             case 4: // tick
1984                                 gen_op_wrtick();
1985                                 break;
1986                             case 5: // tba
1987                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
1988                                 break;
1989                             case 6: // pstate
1990                                 gen_op_wrpstate();
1991                                 save_state(dc);
1992                                 gen_op_next_insn();
1993                                 gen_op_movl_T0_0();
1994                                 gen_op_exit_tb();
1995                                 dc->is_br = 1;
1996                                 break;
1997                             case 7: // tl
1998                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
1999                                 break;
2000                             case 8: // pil
2001                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
2002                                 break;
2003                             case 9: // cwp
2004                                 gen_op_wrcwp();
2005                                 break;
2006                             case 10: // cansave
2007                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
2008                                 break;
2009                             case 11: // canrestore
2010                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
2011                                 break;
2012                             case 12: // cleanwin
2013                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
2014                                 break;
2015                             case 13: // otherwin
2016                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
2017                                 break;
2018                             case 14: // wstate
2019                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
2020                                 break;
2021                             default:
2022                                 goto illegal_insn;
2023                             }
2024 #else
2025                             gen_op_wrwim();
2026 #endif
2027                         }
2028                         break;
2029 #ifndef TARGET_SPARC64
2030                     case 0x33: /* wrtbr, V9 unimp */
2031                         {
2032                             if (!supervisor(dc))
2033                                 goto priv_insn;
2034                             gen_op_xor_T1_T0();
2035                             gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
2036                         }
2037                         break;
2038 #endif
2039 #endif
2040 #ifdef TARGET_SPARC64
2041                     case 0x2c: /* V9 movcc */
2042                         {
2043                             int cc = GET_FIELD_SP(insn, 11, 12);
2044                             int cond = GET_FIELD_SP(insn, 14, 17);
2045                             if (IS_IMM) {       /* immediate */
2046                                 rs2 = GET_FIELD_SPs(insn, 0, 10);
2047                                 gen_movl_simm_T1(rs2);
2048                             }
2049                             else {
2050                                 rs2 = GET_FIELD_SP(insn, 0, 4);
2051                                 gen_movl_reg_T1(rs2);
2052                             }
2053                             gen_movl_reg_T0(rd);
2054                             flush_T2(dc);
2055                             if (insn & (1 << 18)) {
2056                                 if (cc == 0)
2057                                     gen_cond[0][cond]();
2058                                 else if (cc == 2)
2059                                     gen_cond[1][cond]();
2060                                 else
2061                                     goto illegal_insn;
2062                             } else {
2063                                 gen_fcond[cc][cond]();
2064                             }
2065                             gen_op_mov_cc();
2066                             gen_movl_T0_reg(rd);
2067                             break;
2068                         }
2069                     case 0x2d: /* V9 sdivx */
2070                         gen_op_sdivx_T1_T0();
2071                         gen_movl_T0_reg(rd);
2072                         break;
2073                     case 0x2e: /* V9 popc */
2074                         {
2075                             if (IS_IMM) {       /* immediate */
2076                                 rs2 = GET_FIELD_SPs(insn, 0, 12);
2077                                 gen_movl_simm_T1(rs2);
2078                                 // XXX optimize: popc(constant)
2079                             }
2080                             else {
2081                                 rs2 = GET_FIELD_SP(insn, 0, 4);
2082                                 gen_movl_reg_T1(rs2);
2083                             }
2084                             gen_op_popc();
2085                             gen_movl_T0_reg(rd);
2086                         }
2087                     case 0x2f: /* V9 movr */
2088                         {
2089                             int cond = GET_FIELD_SP(insn, 10, 12);
2090                             rs1 = GET_FIELD(insn, 13, 17);
2091                             flush_T2(dc);
2092                             gen_movl_reg_T0(rs1);
2093                             gen_cond_reg(cond);
2094                             if (IS_IMM) {       /* immediate */
2095                                 rs2 = GET_FIELD_SPs(insn, 0, 10);
2096                                 gen_movl_simm_T1(rs2);
2097                             }
2098                             else {
2099                                 rs2 = GET_FIELD_SP(insn, 0, 4);
2100                                 gen_movl_reg_T1(rs2);
2101                             }
2102                             gen_movl_reg_T0(rd);
2103                             gen_op_mov_cc();
2104                             gen_movl_T0_reg(rd);
2105                             break;
2106                         }
2107                     case 0x36: /* UltraSparc shutdown, VIS */
2108                         {
2109                             int opf = GET_FIELD_SP(insn, 5, 13);
2110                             rs1 = GET_FIELD(insn, 13, 17);
2111                             rs2 = GET_FIELD(insn, 27, 31);
2112
2113                             switch (opf) {
2114                             case 0x018: /* VIS I alignaddr */
2115                                 if (gen_trap_ifnofpu(dc))
2116                                     goto jmp_insn;
2117                                 gen_movl_reg_T0(rs1);
2118                                 gen_movl_reg_T1(rs2);
2119                                 gen_op_alignaddr();
2120                                 gen_movl_T0_reg(rd);
2121                                 break;
2122                             case 0x01a: /* VIS I alignaddrl */
2123                                 if (gen_trap_ifnofpu(dc))
2124                                     goto jmp_insn;
2125                                 // XXX
2126                                 break;
2127                             case 0x048: /* VIS I faligndata */
2128                                 if (gen_trap_ifnofpu(dc))
2129                                     goto jmp_insn;
2130                                 gen_op_load_fpr_DT0(rs1);
2131                                 gen_op_load_fpr_DT1(rs2);
2132                                 gen_op_faligndata();
2133                                 gen_op_store_DT0_fpr(rd);
2134                                 break;
2135                             default:
2136                                 goto illegal_insn;
2137                             }
2138                             break;
2139                         }
2140 #endif
2141                     default:
2142                         goto illegal_insn;
2143                     }
2144                 }
2145 #ifdef TARGET_SPARC64
2146             } else if (xop == 0x39) { /* V9 return */
2147                 rs1 = GET_FIELD(insn, 13, 17);
2148                 gen_movl_reg_T0(rs1);
2149                 if (IS_IMM) {   /* immediate */
2150                     rs2 = GET_FIELDs(insn, 19, 31);
2151 #if defined(OPTIM)
2152                     if (rs2) {
2153 #endif
2154                         gen_movl_simm_T1(rs2);
2155                         gen_op_add_T1_T0();
2156 #if defined(OPTIM)
2157                     }
2158 #endif
2159                 } else {                /* register */
2160                     rs2 = GET_FIELD(insn, 27, 31);
2161 #if defined(OPTIM)
2162                     if (rs2) {
2163 #endif
2164                         gen_movl_reg_T1(rs2);
2165                         gen_op_add_T1_T0();
2166 #if defined(OPTIM)
2167                     }
2168 #endif
2169                 }
2170                 gen_op_restore();
2171                 gen_mov_pc_npc(dc);
2172                 gen_op_movl_npc_T0();
2173                 dc->npc = DYNAMIC_PC;
2174                 goto jmp_insn;
2175 #endif
2176             } else {
2177                 rs1 = GET_FIELD(insn, 13, 17);
2178                 gen_movl_reg_T0(rs1);
2179                 if (IS_IMM) {   /* immediate */
2180                     rs2 = GET_FIELDs(insn, 19, 31);
2181 #if defined(OPTIM)
2182                     if (rs2) {
2183 #endif
2184                         gen_movl_simm_T1(rs2);
2185                         gen_op_add_T1_T0();
2186 #if defined(OPTIM)
2187                     }
2188 #endif
2189                 } else {                /* register */
2190                     rs2 = GET_FIELD(insn, 27, 31);
2191 #if defined(OPTIM)
2192                     if (rs2) {
2193 #endif
2194                         gen_movl_reg_T1(rs2);
2195                         gen_op_add_T1_T0();
2196 #if defined(OPTIM)
2197                     }
2198 #endif
2199                 }
2200                 switch (xop) {
2201                 case 0x38:      /* jmpl */
2202                     {
2203                         if (rd != 0) {
2204 #ifdef TARGET_SPARC64
2205                             if (dc->pc == (uint32_t)dc->pc) {
2206                                 gen_op_movl_T1_im(dc->pc);
2207                             } else {
2208                                 gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
2209                             }
2210 #else
2211                             gen_op_movl_T1_im(dc->pc);
2212 #endif
2213                             gen_movl_T1_reg(rd);
2214                         }
2215                         gen_mov_pc_npc(dc);
2216                         gen_op_movl_npc_T0();
2217                         dc->npc = DYNAMIC_PC;
2218                     }
2219                     goto jmp_insn;
2220 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2221                 case 0x39:      /* rett, V9 return */
2222                     {
2223                         if (!supervisor(dc))
2224                             goto priv_insn;
2225                         gen_mov_pc_npc(dc);
2226                         gen_op_movl_npc_T0();
2227                         dc->npc = DYNAMIC_PC;
2228                         gen_op_rett();
2229                     }
2230                     goto jmp_insn;
2231 #endif
2232                 case 0x3b: /* flush */
2233                     gen_op_flush_T0();
2234                     break;
2235                 case 0x3c:      /* save */
2236                     save_state(dc);
2237                     gen_op_save();
2238                     gen_movl_T0_reg(rd);
2239                     break;
2240                 case 0x3d:      /* restore */
2241                     save_state(dc);
2242                     gen_op_restore();
2243                     gen_movl_T0_reg(rd);
2244                     break;
2245 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
2246                 case 0x3e:      /* V9 done/retry */
2247                     {
2248                         switch (rd) {
2249                         case 0:
2250                             if (!supervisor(dc))
2251                                 goto priv_insn;
2252                             dc->npc = DYNAMIC_PC;
2253                             dc->pc = DYNAMIC_PC;
2254                             gen_op_done();
2255                             goto jmp_insn;
2256                         case 1:
2257                             if (!supervisor(dc))
2258                                 goto priv_insn;
2259                             dc->npc = DYNAMIC_PC;
2260                             dc->pc = DYNAMIC_PC;
2261                             gen_op_retry();
2262                             goto jmp_insn;
2263                         default:
2264                             goto illegal_insn;
2265                         }
2266                     }
2267                     break;
2268 #endif
2269                 default:
2270                     goto illegal_insn;
2271                 }
2272             }
2273             break;
2274         }
2275         break;
2276     case 3:                     /* load/store instructions */
2277         {
2278             unsigned int xop = GET_FIELD(insn, 7, 12);
2279             rs1 = GET_FIELD(insn, 13, 17);
2280             gen_movl_reg_T0(rs1);
2281             if (IS_IMM) {       /* immediate */
2282                 rs2 = GET_FIELDs(insn, 19, 31);
2283 #if defined(OPTIM)
2284                 if (rs2 != 0) {
2285 #endif
2286                     gen_movl_simm_T1(rs2);
2287                     gen_op_add_T1_T0();
2288 #if defined(OPTIM)
2289                 }
2290 #endif
2291             } else {            /* register */
2292                 rs2 = GET_FIELD(insn, 27, 31);
2293 #if defined(OPTIM)
2294                 if (rs2 != 0) {
2295 #endif
2296                     gen_movl_reg_T1(rs2);
2297                     gen_op_add_T1_T0();
2298 #if defined(OPTIM)
2299                 }
2300 #endif
2301             }
2302             if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
2303                     (xop > 0x17 && xop < 0x1d ) || \
2304                     (xop > 0x2c && xop < 0x33) || xop == 0x1f) {
2305                 switch (xop) {
2306                 case 0x0:       /* load word */
2307                     gen_op_ldst(ld);
2308                     break;
2309                 case 0x1:       /* load unsigned byte */
2310                     gen_op_ldst(ldub);
2311                     break;
2312                 case 0x2:       /* load unsigned halfword */
2313                     gen_op_ldst(lduh);
2314                     break;
2315                 case 0x3:       /* load double word */
2316                     gen_op_ldst(ldd);
2317                     gen_movl_T0_reg(rd + 1);
2318                     break;
2319                 case 0x9:       /* load signed byte */
2320                     gen_op_ldst(ldsb);
2321                     break;
2322                 case 0xa:       /* load signed halfword */
2323                     gen_op_ldst(ldsh);
2324                     break;
2325                 case 0xd:       /* ldstub -- XXX: should be atomically */
2326                     gen_op_ldst(ldstub);
2327                     break;
2328                 case 0x0f:      /* swap register with memory. Also atomically */
2329                     gen_movl_reg_T1(rd);
2330                     gen_op_ldst(swap);
2331                     break;
2332 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2333                 case 0x10:      /* load word alternate */
2334 #ifndef TARGET_SPARC64
2335                     if (!supervisor(dc))
2336                         goto priv_insn;
2337 #endif
2338                     gen_op_lda(insn, 1, 4, 0);
2339                     break;
2340                 case 0x11:      /* load unsigned byte alternate */
2341 #ifndef TARGET_SPARC64
2342                     if (!supervisor(dc))
2343                         goto priv_insn;
2344 #endif
2345                     gen_op_lduba(insn, 1, 1, 0);
2346                     break;
2347                 case 0x12:      /* load unsigned halfword alternate */
2348 #ifndef TARGET_SPARC64
2349                     if (!supervisor(dc))
2350                         goto priv_insn;
2351 #endif
2352                     gen_op_lduha(insn, 1, 2, 0);
2353                     break;
2354                 case 0x13:      /* load double word alternate */
2355 #ifndef TARGET_SPARC64
2356                     if (!supervisor(dc))
2357                         goto priv_insn;
2358 #endif
2359                     gen_op_ldda(insn, 1, 8, 0);
2360                     gen_movl_T0_reg(rd + 1);
2361                     break;
2362                 case 0x19:      /* load signed byte alternate */
2363 #ifndef TARGET_SPARC64
2364                     if (!supervisor(dc))
2365                         goto priv_insn;
2366 #endif
2367                     gen_op_ldsba(insn, 1, 1, 1);
2368                     break;
2369                 case 0x1a:      /* load signed halfword alternate */
2370 #ifndef TARGET_SPARC64
2371                     if (!supervisor(dc))
2372                         goto priv_insn;
2373 #endif
2374                     gen_op_ldsha(insn, 1, 2 ,1);
2375                     break;
2376                 case 0x1d:      /* ldstuba -- XXX: should be atomically */
2377 #ifndef TARGET_SPARC64
2378                     if (!supervisor(dc))
2379                         goto priv_insn;
2380 #endif
2381                     gen_op_ldstuba(insn, 1, 1, 0);
2382                     break;
2383                 case 0x1f:      /* swap reg with alt. memory. Also atomically */
2384 #ifndef TARGET_SPARC64
2385                     if (!supervisor(dc))
2386                         goto priv_insn;
2387 #endif
2388                     gen_movl_reg_T1(rd);
2389                     gen_op_swapa(insn, 1, 4, 0);
2390                     break;
2391
2392 #ifndef TARGET_SPARC64
2393                     /* avoid warnings */
2394                     (void) &gen_op_stfa;
2395                     (void) &gen_op_stdfa;
2396                     (void) &gen_op_ldfa;
2397                     (void) &gen_op_lddfa;
2398 #else
2399 #if !defined(CONFIG_USER_ONLY)
2400                     (void) &gen_op_cas;
2401                     (void) &gen_op_casx;
2402 #endif
2403 #endif
2404 #endif
2405 #ifdef TARGET_SPARC64
2406                 case 0x08: /* V9 ldsw */
2407                     gen_op_ldst(ldsw);
2408                     break;
2409                 case 0x0b: /* V9 ldx */
2410                     gen_op_ldst(ldx);
2411                     break;
2412                 case 0x18: /* V9 ldswa */
2413                     gen_op_ldswa(insn, 1, 4, 1);
2414                     break;
2415                 case 0x1b: /* V9 ldxa */
2416                     gen_op_ldxa(insn, 1, 8, 0);
2417                     break;
2418                 case 0x2d: /* V9 prefetch, no effect */
2419                     goto skip_move;
2420                 case 0x30: /* V9 ldfa */
2421                     gen_op_ldfa(insn, 1, 8, 0); // XXX
2422                     break;
2423                 case 0x33: /* V9 lddfa */
2424                     gen_op_lddfa(insn, 1, 8, 0); // XXX
2425
2426                     break;
2427                 case 0x3d: /* V9 prefetcha, no effect */
2428                     goto skip_move;
2429                 case 0x32: /* V9 ldqfa */
2430                     goto nfpu_insn;
2431 #endif
2432                 default:
2433                     goto illegal_insn;
2434                 }
2435                 gen_movl_T1_reg(rd);
2436 #ifdef TARGET_SPARC64
2437             skip_move: ;
2438 #endif
2439             } else if (xop >= 0x20 && xop < 0x24) {
2440                 if (gen_trap_ifnofpu(dc))
2441                     goto jmp_insn;
2442                 switch (xop) {
2443                 case 0x20:      /* load fpreg */
2444                     gen_op_ldst(ldf);
2445                     gen_op_store_FT0_fpr(rd);
2446                     break;
2447                 case 0x21:      /* load fsr */
2448                     gen_op_ldst(ldf);
2449                     gen_op_ldfsr();
2450                     break;
2451                 case 0x22:      /* load quad fpreg */
2452                     goto nfpu_insn;
2453                 case 0x23:      /* load double fpreg */
2454                     gen_op_ldst(lddf);
2455                     gen_op_store_DT0_fpr(DFPREG(rd));
2456                     break;
2457                 default:
2458                     goto illegal_insn;
2459                 }
2460             } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
2461                        xop == 0xe || xop == 0x1e) {
2462                 gen_movl_reg_T1(rd);
2463                 switch (xop) {
2464                 case 0x4:
2465                     gen_op_ldst(st);
2466                     break;
2467                 case 0x5:
2468                     gen_op_ldst(stb);
2469                     break;
2470                 case 0x6:
2471                     gen_op_ldst(sth);
2472                     break;
2473                 case 0x7:
2474                     flush_T2(dc);
2475                     gen_movl_reg_T2(rd + 1);
2476                     gen_op_ldst(std);
2477                     break;
2478 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2479                 case 0x14:
2480 #ifndef TARGET_SPARC64
2481                     if (!supervisor(dc))
2482                         goto priv_insn;
2483 #endif
2484                     gen_op_sta(insn, 0, 4, 0);
2485                     break;
2486                 case 0x15:
2487 #ifndef TARGET_SPARC64
2488                     if (!supervisor(dc))
2489                         goto priv_insn;
2490 #endif
2491                     gen_op_stba(insn, 0, 1, 0);
2492                     break;
2493                 case 0x16:
2494 #ifndef TARGET_SPARC64
2495                     if (!supervisor(dc))
2496                         goto priv_insn;
2497 #endif
2498                     gen_op_stha(insn, 0, 2, 0);
2499                     break;
2500                 case 0x17:
2501 #ifndef TARGET_SPARC64
2502                     if (!supervisor(dc))
2503                         goto priv_insn;
2504 #endif
2505                     flush_T2(dc);
2506                     gen_movl_reg_T2(rd + 1);
2507                     gen_op_stda(insn, 0, 8, 0);
2508                     break;
2509 #endif
2510 #ifdef TARGET_SPARC64
2511                 case 0x0e: /* V9 stx */
2512                     gen_op_ldst(stx);
2513                     break;
2514                 case 0x1e: /* V9 stxa */
2515                     gen_op_stxa(insn, 0, 8, 0); // XXX
2516                     break;
2517 #endif
2518                 default:
2519                     goto illegal_insn;
2520                 }
2521             } else if (xop > 0x23 && xop < 0x28) {
2522                 if (gen_trap_ifnofpu(dc))
2523                     goto jmp_insn;
2524                 switch (xop) {
2525                 case 0x24:
2526                     gen_op_load_fpr_FT0(rd);
2527                     gen_op_ldst(stf);
2528                     break;
2529                 case 0x25: /* stfsr, V9 stxfsr */
2530                     gen_op_stfsr();
2531                     gen_op_ldst(stf);
2532                     break;
2533                 case 0x26: /* stdfq */
2534                     goto nfpu_insn;
2535                 case 0x27:
2536                     gen_op_load_fpr_DT0(DFPREG(rd));
2537                     gen_op_ldst(stdf);
2538                     break;
2539                 default:
2540                     goto illegal_insn;
2541                 }
2542             } else if (xop > 0x33 && xop < 0x3f) {
2543 #ifdef TARGET_SPARC64
2544                 switch (xop) {
2545                 case 0x34: /* V9 stfa */
2546                     gen_op_stfa(insn, 0, 0, 0); // XXX
2547                     break;
2548                 case 0x37: /* V9 stdfa */
2549                     gen_op_stdfa(insn, 0, 0, 0); // XXX
2550                     break;
2551                 case 0x3c: /* V9 casa */
2552                     gen_op_casa(insn, 0, 4, 0); // XXX
2553                     break;
2554                 case 0x3e: /* V9 casxa */
2555                     gen_op_casxa(insn, 0, 8, 0); // XXX
2556                     break;
2557                 case 0x36: /* V9 stqfa */
2558                     goto nfpu_insn;
2559                 default:
2560                     goto illegal_insn;
2561                 }
2562 #else
2563                 goto illegal_insn;
2564 #endif
2565             }
2566             else
2567                 goto illegal_insn;
2568         }
2569         break;
2570     }
2571     /* default case for non jump instructions */
2572     if (dc->npc == DYNAMIC_PC) {
2573         dc->pc = DYNAMIC_PC;
2574         gen_op_next_insn();
2575     } else if (dc->npc == JUMP_PC) {
2576         /* we can do a static jump */
2577         gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
2578         dc->is_br = 1;
2579     } else {
2580         dc->pc = dc->npc;
2581         dc->npc = dc->npc + 4;
2582     }
2583  jmp_insn:
2584     return;
2585  illegal_insn:
2586     save_state(dc);
2587     gen_op_exception(TT_ILL_INSN);
2588     dc->is_br = 1;
2589     return;
2590 #if !defined(CONFIG_USER_ONLY)
2591  priv_insn:
2592     save_state(dc);
2593     gen_op_exception(TT_PRIV_INSN);
2594     dc->is_br = 1;
2595     return;
2596 #endif
2597  nfpu_insn:
2598     save_state(dc);
2599     gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
2600     dc->is_br = 1;
2601 }
2602
2603 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2604                                                  int spc, CPUSPARCState *env)
2605 {
2606     target_ulong pc_start, last_pc;
2607     uint16_t *gen_opc_end;
2608     DisasContext dc1, *dc = &dc1;
2609     int j, lj = -1;
2610
2611     memset(dc, 0, sizeof(DisasContext));
2612     dc->tb = tb;
2613     pc_start = tb->pc;
2614     dc->pc = pc_start;
2615     last_pc = dc->pc;
2616     dc->npc = (target_ulong) tb->cs_base;
2617 #if defined(CONFIG_USER_ONLY)
2618     dc->mem_idx = 0;
2619     dc->fpu_enabled = 1;
2620 #else
2621     dc->mem_idx = ((env->psrs) != 0);
2622 #ifdef TARGET_SPARC64
2623     dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
2624 #else
2625     dc->fpu_enabled = ((env->psref) != 0);
2626 #endif
2627 #endif
2628     gen_opc_ptr = gen_opc_buf;
2629     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2630     gen_opparam_ptr = gen_opparam_buf;
2631     nb_gen_labels = 0;
2632
2633     do {
2634         if (env->nb_breakpoints > 0) {
2635             for(j = 0; j < env->nb_breakpoints; j++) {
2636                 if (env->breakpoints[j] == dc->pc) {
2637                     if (dc->pc != pc_start)
2638                         save_state(dc);
2639                     gen_op_debug();
2640                     gen_op_movl_T0_0();
2641                     gen_op_exit_tb();
2642                     dc->is_br = 1;
2643                     goto exit_gen_loop;
2644                 }
2645             }
2646         }
2647         if (spc) {
2648             if (loglevel > 0)
2649                 fprintf(logfile, "Search PC...\n");
2650             j = gen_opc_ptr - gen_opc_buf;
2651             if (lj < j) {
2652                 lj++;
2653                 while (lj < j)
2654                     gen_opc_instr_start[lj++] = 0;
2655                 gen_opc_pc[lj] = dc->pc;
2656                 gen_opc_npc[lj] = dc->npc;
2657                 gen_opc_instr_start[lj] = 1;
2658             }
2659         }
2660         last_pc = dc->pc;
2661         disas_sparc_insn(dc);
2662
2663         if (dc->is_br)
2664             break;
2665         /* if the next PC is different, we abort now */
2666         if (dc->pc != (last_pc + 4))
2667             break;
2668         /* if we reach a page boundary, we stop generation so that the
2669            PC of a TT_TFAULT exception is always in the right page */
2670         if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
2671             break;
2672         /* if single step mode, we generate only one instruction and
2673            generate an exception */
2674         if (env->singlestep_enabled) {
2675             gen_jmp_im(dc->pc);
2676             gen_op_movl_T0_0();
2677             gen_op_exit_tb();
2678             break;
2679         }
2680     } while ((gen_opc_ptr < gen_opc_end) &&
2681              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2682
2683  exit_gen_loop:
2684     if (!dc->is_br) {
2685         if (dc->pc != DYNAMIC_PC && 
2686             (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2687             /* static PC and NPC: we can use direct chaining */
2688             gen_branch(dc, (long)tb, dc->pc, dc->npc);
2689         } else {
2690             if (dc->pc != DYNAMIC_PC)
2691                 gen_jmp_im(dc->pc);
2692             save_npc(dc);
2693             gen_op_movl_T0_0();
2694             gen_op_exit_tb();
2695         }
2696     }
2697     *gen_opc_ptr = INDEX_op_end;
2698     if (spc) {
2699         j = gen_opc_ptr - gen_opc_buf;
2700         lj++;
2701         while (lj <= j)
2702             gen_opc_instr_start[lj++] = 0;
2703         tb->size = 0;
2704 #if 0
2705         if (loglevel > 0) {
2706             page_dump(logfile);
2707         }
2708 #endif
2709         gen_opc_jump_pc[0] = dc->jump_pc[0];
2710         gen_opc_jump_pc[1] = dc->jump_pc[1];
2711     } else {
2712         tb->size = last_pc + 4 - pc_start;
2713     }
2714 #ifdef DEBUG_DISAS
2715     if (loglevel & CPU_LOG_TB_IN_ASM) {
2716         fprintf(logfile, "--------------\n");
2717         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2718         target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2719         fprintf(logfile, "\n");
2720         if (loglevel & CPU_LOG_TB_OP) {
2721             fprintf(logfile, "OP:\n");
2722             dump_ops(gen_opc_buf, gen_opparam_buf);
2723             fprintf(logfile, "\n");
2724         }
2725     }
2726 #endif
2727     return 0;
2728 }
2729
2730 int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2731 {
2732     return gen_intermediate_code_internal(tb, 0, env);
2733 }
2734
2735 int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2736 {
2737     return gen_intermediate_code_internal(tb, 1, env);
2738 }
2739
2740 extern int ram_size;
2741
2742 void cpu_reset(CPUSPARCState *env)
2743 {
2744     memset(env, 0, sizeof(*env));
2745     tlb_flush(env, 1);
2746     env->cwp = 0;
2747     env->wim = 1;
2748     env->regwptr = env->regbase + (env->cwp * 16);
2749 #if defined(CONFIG_USER_ONLY)
2750     env->user_mode_only = 1;
2751 #ifdef TARGET_SPARC64
2752     env->cleanwin = NWINDOWS - 1;
2753     env->cansave = NWINDOWS - 1;
2754 #endif
2755 #else
2756     env->psrs = 1;
2757     env->psrps = 1;
2758     env->gregs[1] = ram_size;
2759 #ifdef TARGET_SPARC64
2760     env->pstate = PS_PRIV;
2761     env->pc = 0x1fff0000000ULL;
2762 #else
2763     env->pc = 0xffd00000;
2764 #endif
2765     env->npc = env->pc + 4;
2766 #endif
2767 }
2768
2769 CPUSPARCState *cpu_sparc_init(void)
2770 {
2771     CPUSPARCState *env;
2772
2773     env = qemu_mallocz(sizeof(CPUSPARCState));
2774     if (!env)
2775         return NULL;
2776     cpu_exec_init(env);
2777     cpu_reset(env);
2778     return (env);
2779 }
2780
2781 static const sparc_def_t sparc_defs[] = {
2782 #ifdef TARGET_SPARC64
2783     {
2784         .name = "TI UltraSparc II",
2785         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
2786                        | (MAXTL << 8) | (NWINDOWS - 1)),
2787         .fpu_version = 0x00000000,
2788         .mmu_version = 0,
2789     },
2790 #else
2791     {
2792         .name = "Fujitsu MB86904",
2793         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
2794         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
2795         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
2796     },
2797 #endif
2798 };
2799
2800 int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
2801 {
2802     int ret;
2803     unsigned int i;
2804
2805     ret = -1;
2806     *def = NULL;
2807     for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2808         if (strcasecmp(name, sparc_defs[i].name) == 0) {
2809             *def = &sparc_defs[i];
2810             ret = 0;
2811             break;
2812         }
2813     }
2814
2815     return ret;
2816 }
2817
2818 void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2819 {
2820     unsigned int i;
2821
2822     for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2823         (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
2824                        sparc_defs[i].name,
2825                        sparc_defs[i].iu_version,
2826                        sparc_defs[i].fpu_version,
2827                        sparc_defs[i].mmu_version);
2828     }
2829 }
2830
2831 int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
2832 {
2833     env->version = def->iu_version;
2834     env->fsr = def->fpu_version;
2835 #if !defined(TARGET_SPARC64)
2836     env->mmuregs[0] = def->mmu_version;
2837 #endif
2838     return 0;
2839 }
2840
2841 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
2842
2843 void cpu_dump_state(CPUState *env, FILE *f, 
2844                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2845                     int flags)
2846 {
2847     int i, x;
2848
2849     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
2850     cpu_fprintf(f, "General Registers:\n");
2851     for (i = 0; i < 4; i++)
2852         cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2853     cpu_fprintf(f, "\n");
2854     for (; i < 8; i++)
2855         cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2856     cpu_fprintf(f, "\nCurrent Register Window:\n");
2857     for (x = 0; x < 3; x++) {
2858         for (i = 0; i < 4; i++)
2859             cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2860                     (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
2861                     env->regwptr[i + x * 8]);
2862         cpu_fprintf(f, "\n");
2863         for (; i < 8; i++)
2864             cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2865                     (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
2866                     env->regwptr[i + x * 8]);
2867         cpu_fprintf(f, "\n");
2868     }
2869     cpu_fprintf(f, "\nFloating Point Registers:\n");
2870     for (i = 0; i < 32; i++) {
2871         if ((i & 3) == 0)
2872             cpu_fprintf(f, "%%f%02d:", i);
2873         cpu_fprintf(f, " %016lf", env->fpr[i]);
2874         if ((i & 3) == 3)
2875             cpu_fprintf(f, "\n");
2876     }
2877 #ifdef TARGET_SPARC64
2878     cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
2879                 env->pstate, GET_CCR(env), env->asi, env->tl);
2880     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
2881                 env->cansave, env->canrestore, env->otherwin, env->wstate,
2882                 env->cleanwin, NWINDOWS - 1 - env->cwp);
2883 #else
2884     cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
2885             GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
2886             GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
2887             env->psrs?'S':'-', env->psrps?'P':'-', 
2888             env->psret?'E':'-', env->wim);
2889 #endif
2890     cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
2891 }
2892
2893 #if defined(CONFIG_USER_ONLY)
2894 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2895 {
2896     return addr;
2897 }
2898
2899 #else
2900 extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
2901                                  int *access_index, target_ulong address, int rw,
2902                                  int is_user);
2903
2904 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2905 {
2906     target_phys_addr_t phys_addr;
2907     int prot, access_index;
2908
2909     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
2910         if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
2911             return -1;
2912     return phys_addr;
2913 }
2914 #endif
2915
2916 void helper_flush(target_ulong addr)
2917 {
2918     addr &= ~7;
2919     tb_invalidate_page_range(addr, addr + 8);
2920 }