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