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