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