Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ 9143e598

History | View | Annotate | Download (80.1 kB)

1
/*
2
   SPARC translation
3

4
   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5
   Copyright (C) 2003-2005 Fabrice Bellard
6

7
   This library is free software; you can redistribute it and/or
8
   modify it under the terms of the GNU Lesser General Public
9
   License as published by the Free Software Foundation; either
10
   version 2 of the License, or (at your option) any later version.
11

12
   This library is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
   Lesser General Public License for more details.
16

17
   You should have received a copy of the GNU Lesser General Public
18
   License along with this library; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21

    
22
/*
23
   TODO-list:
24

25
   Rest of V9 instructions, VIS instructions
26
   NPC/PC static optimisations (use JUMP_TB when possible)
27
   Optimize synthetic instructions
28
   Optional alignment check
29
   128-bit float
30
*/
31

    
32
#include <stdarg.h>
33
#include <stdlib.h>
34
#include <stdio.h>
35
#include <string.h>
36
#include <inttypes.h>
37

    
38
#include "cpu.h"
39
#include "exec-all.h"
40
#include "disas.h"
41

    
42
#define DEBUG_DISAS
43

    
44
#define DYNAMIC_PC  1 /* dynamic pc value */
45
#define JUMP_PC     2 /* dynamic pc value which takes only two values
46
                         according to jump_pc[T2] */
47

    
48
typedef struct DisasContext {
49
    target_ulong pc;        /* current Program Counter: integer or DYNAMIC_PC */
50
    target_ulong npc;        /* next PC: integer or DYNAMIC_PC or JUMP_PC */
51
    target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
52
    int is_br;
53
    int mem_idx;
54
    int fpu_enabled;
55
    struct TranslationBlock *tb;
56
} DisasContext;
57

    
58
struct sparc_def_t {
59
    const unsigned char *name;
60
    target_ulong iu_version;
61
    uint32_t fpu_version;
62
    uint32_t mmu_version;
63
};
64

    
65
static uint16_t *gen_opc_ptr;
66
static uint32_t *gen_opparam_ptr;
67
extern FILE *logfile;
68
extern int loglevel;
69

    
70
enum {
71
#define DEF(s,n,copy_size) INDEX_op_ ## s,
72
#include "opc.h"
73
#undef DEF
74
    NB_OPS
75
};
76

    
77
#include "gen-op.h"
78

    
79
// This function uses non-native bit order
80
#define GET_FIELD(X, FROM, TO) \
81
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
82

    
83
// This function uses the order in the manuals, i.e. bit 0 is 2^0
84
#define GET_FIELD_SP(X, FROM, TO) \
85
    GET_FIELD(X, 31 - (TO), 31 - (FROM))
86

    
87
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
88
#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), 32 - ((b) - (a) + 1))
89

    
90
#ifdef TARGET_SPARC64
91
#define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
92
#else
93
#define DFPREG(r) (r)
94
#endif
95

    
96
#ifdef USE_DIRECT_JUMP
97
#define TBPARAM(x)
98
#else
99
#define TBPARAM(x) (long)(x)
100
#endif
101

    
102
static int sign_extend(int x, int len)
103
{
104
    len = 32 - len;
105
    return (x << len) >> len;
106
}
107

    
108
#define IS_IMM (insn & (1<<13))
109

    
110
static void disas_sparc_insn(DisasContext * dc);
111

    
112
static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
113
    {
114
     gen_op_movl_g0_T0,
115
     gen_op_movl_g1_T0,
116
     gen_op_movl_g2_T0,
117
     gen_op_movl_g3_T0,
118
     gen_op_movl_g4_T0,
119
     gen_op_movl_g5_T0,
120
     gen_op_movl_g6_T0,
121
     gen_op_movl_g7_T0,
122
     gen_op_movl_o0_T0,
123
     gen_op_movl_o1_T0,
124
     gen_op_movl_o2_T0,
125
     gen_op_movl_o3_T0,
126
     gen_op_movl_o4_T0,
127
     gen_op_movl_o5_T0,
128
     gen_op_movl_o6_T0,
129
     gen_op_movl_o7_T0,
130
     gen_op_movl_l0_T0,
131
     gen_op_movl_l1_T0,
132
     gen_op_movl_l2_T0,
133
     gen_op_movl_l3_T0,
134
     gen_op_movl_l4_T0,
135
     gen_op_movl_l5_T0,
136
     gen_op_movl_l6_T0,
137
     gen_op_movl_l7_T0,
138
     gen_op_movl_i0_T0,
139
     gen_op_movl_i1_T0,
140
     gen_op_movl_i2_T0,
141
     gen_op_movl_i3_T0,
142
     gen_op_movl_i4_T0,
143
     gen_op_movl_i5_T0,
144
     gen_op_movl_i6_T0,
145
     gen_op_movl_i7_T0,
146
     },
147
    {
148
     gen_op_movl_g0_T1,
149
     gen_op_movl_g1_T1,
150
     gen_op_movl_g2_T1,
151
     gen_op_movl_g3_T1,
152
     gen_op_movl_g4_T1,
153
     gen_op_movl_g5_T1,
154
     gen_op_movl_g6_T1,
155
     gen_op_movl_g7_T1,
156
     gen_op_movl_o0_T1,
157
     gen_op_movl_o1_T1,
158
     gen_op_movl_o2_T1,
159
     gen_op_movl_o3_T1,
160
     gen_op_movl_o4_T1,
161
     gen_op_movl_o5_T1,
162
     gen_op_movl_o6_T1,
163
     gen_op_movl_o7_T1,
164
     gen_op_movl_l0_T1,
165
     gen_op_movl_l1_T1,
166
     gen_op_movl_l2_T1,
167
     gen_op_movl_l3_T1,
168
     gen_op_movl_l4_T1,
169
     gen_op_movl_l5_T1,
170
     gen_op_movl_l6_T1,
171
     gen_op_movl_l7_T1,
172
     gen_op_movl_i0_T1,
173
     gen_op_movl_i1_T1,
174
     gen_op_movl_i2_T1,
175
     gen_op_movl_i3_T1,
176
     gen_op_movl_i4_T1,
177
     gen_op_movl_i5_T1,
178
     gen_op_movl_i6_T1,
179
     gen_op_movl_i7_T1,
180
     }
181
};
182

    
183
static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
184
    {
185
     gen_op_movl_T0_g0,
186
     gen_op_movl_T0_g1,
187
     gen_op_movl_T0_g2,
188
     gen_op_movl_T0_g3,
189
     gen_op_movl_T0_g4,
190
     gen_op_movl_T0_g5,
191
     gen_op_movl_T0_g6,
192
     gen_op_movl_T0_g7,
193
     gen_op_movl_T0_o0,
194
     gen_op_movl_T0_o1,
195
     gen_op_movl_T0_o2,
196
     gen_op_movl_T0_o3,
197
     gen_op_movl_T0_o4,
198
     gen_op_movl_T0_o5,
199
     gen_op_movl_T0_o6,
200
     gen_op_movl_T0_o7,
201
     gen_op_movl_T0_l0,
202
     gen_op_movl_T0_l1,
203
     gen_op_movl_T0_l2,
204
     gen_op_movl_T0_l3,
205
     gen_op_movl_T0_l4,
206
     gen_op_movl_T0_l5,
207
     gen_op_movl_T0_l6,
208
     gen_op_movl_T0_l7,
209
     gen_op_movl_T0_i0,
210
     gen_op_movl_T0_i1,
211
     gen_op_movl_T0_i2,
212
     gen_op_movl_T0_i3,
213
     gen_op_movl_T0_i4,
214
     gen_op_movl_T0_i5,
215
     gen_op_movl_T0_i6,
216
     gen_op_movl_T0_i7,
217
     },
218
    {
219
     gen_op_movl_T1_g0,
220
     gen_op_movl_T1_g1,
221
     gen_op_movl_T1_g2,
222
     gen_op_movl_T1_g3,
223
     gen_op_movl_T1_g4,
224
     gen_op_movl_T1_g5,
225
     gen_op_movl_T1_g6,
226
     gen_op_movl_T1_g7,
227
     gen_op_movl_T1_o0,
228
     gen_op_movl_T1_o1,
229
     gen_op_movl_T1_o2,
230
     gen_op_movl_T1_o3,
231
     gen_op_movl_T1_o4,
232
     gen_op_movl_T1_o5,
233
     gen_op_movl_T1_o6,
234
     gen_op_movl_T1_o7,
235
     gen_op_movl_T1_l0,
236
     gen_op_movl_T1_l1,
237
     gen_op_movl_T1_l2,
238
     gen_op_movl_T1_l3,
239
     gen_op_movl_T1_l4,
240
     gen_op_movl_T1_l5,
241
     gen_op_movl_T1_l6,
242
     gen_op_movl_T1_l7,
243
     gen_op_movl_T1_i0,
244
     gen_op_movl_T1_i1,
245
     gen_op_movl_T1_i2,
246
     gen_op_movl_T1_i3,
247
     gen_op_movl_T1_i4,
248
     gen_op_movl_T1_i5,
249
     gen_op_movl_T1_i6,
250
     gen_op_movl_T1_i7,
251
     },
252
    {
253
     gen_op_movl_T2_g0,
254
     gen_op_movl_T2_g1,
255
     gen_op_movl_T2_g2,
256
     gen_op_movl_T2_g3,
257
     gen_op_movl_T2_g4,
258
     gen_op_movl_T2_g5,
259
     gen_op_movl_T2_g6,
260
     gen_op_movl_T2_g7,
261
     gen_op_movl_T2_o0,
262
     gen_op_movl_T2_o1,
263
     gen_op_movl_T2_o2,
264
     gen_op_movl_T2_o3,
265
     gen_op_movl_T2_o4,
266
     gen_op_movl_T2_o5,
267
     gen_op_movl_T2_o6,
268
     gen_op_movl_T2_o7,
269
     gen_op_movl_T2_l0,
270
     gen_op_movl_T2_l1,
271
     gen_op_movl_T2_l2,
272
     gen_op_movl_T2_l3,
273
     gen_op_movl_T2_l4,
274
     gen_op_movl_T2_l5,
275
     gen_op_movl_T2_l6,
276
     gen_op_movl_T2_l7,
277
     gen_op_movl_T2_i0,
278
     gen_op_movl_T2_i1,
279
     gen_op_movl_T2_i2,
280
     gen_op_movl_T2_i3,
281
     gen_op_movl_T2_i4,
282
     gen_op_movl_T2_i5,
283
     gen_op_movl_T2_i6,
284
     gen_op_movl_T2_i7,
285
     }
286
};
287

    
288
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
289
    gen_op_movl_T0_im,
290
    gen_op_movl_T1_im,
291
    gen_op_movl_T2_im
292
};
293

    
294
// Sign extending version
295
static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
296
    gen_op_movl_T0_sim,
297
    gen_op_movl_T1_sim,
298
    gen_op_movl_T2_sim
299
};
300

    
301
#ifdef TARGET_SPARC64
302
#define GEN32(func, NAME) \
303
static GenOpFunc *NAME ## _table [64] = {                                     \
304
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
305
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
306
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
307
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
308
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
309
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
310
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
311
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
312
NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0,                   \
313
NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0,                   \
314
NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0,                   \
315
NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0,                   \
316
};                                                                            \
317
static inline void func(int n)                                                \
318
{                                                                             \
319
    NAME ## _table[n]();                                                      \
320
}
321
#else
322
#define GEN32(func, NAME) \
323
static GenOpFunc *NAME ## _table [32] = {                                     \
324
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
325
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
326
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
327
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
328
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
329
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
330
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
331
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
332
};                                                                            \
333
static inline void func(int n)                                                \
334
{                                                                             \
335
    NAME ## _table[n]();                                                      \
336
}
337
#endif
338

    
339
/* floating point registers moves */
340
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
341
GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
342
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
343
GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
344

    
345
GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
346
GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
347
GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
348
GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
349

    
350
#ifdef TARGET_SPARC64
351
// 'a' versions allowed to user depending on asi
352
#if defined(CONFIG_USER_ONLY)
353
#define supervisor(dc) 0
354
#define gen_op_ldst(name)        gen_op_##name##_raw()
355
#define OP_LD_TABLE(width)                                                \
356
    static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
357
    {                                                                        \
358
        int asi, offset;                                                \
359
                                                                        \
360
        if (IS_IMM) {                                                        \
361
            offset = GET_FIELD(insn, 25, 31);                                \
362
            if (is_ld)                                                        \
363
                gen_op_ld_asi_reg(offset, size, sign);                        \
364
            else                                                        \
365
                gen_op_st_asi_reg(offset, size, sign);                        \
366
            return;                                                        \
367
        }                                                                \
368
        asi = GET_FIELD(insn, 19, 26);                                        \
369
        switch (asi) {                                                        \
370
        case 0x80: /* Primary address space */                                \
371
            gen_op_##width##_raw();                                        \
372
            break;                                                        \
373
        case 0x82: /* Primary address space, non-faulting load */       \
374
            gen_op_##width##_raw();                                        \
375
            break;                                                        \
376
        default:                                                        \
377
            break;                                                        \
378
        }                                                                \
379
    }
380

    
381
#else
382
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
383
#define OP_LD_TABLE(width)                                                \
384
    static GenOpFunc *gen_op_##width[] = {                                \
385
        &gen_op_##width##_user,                                                \
386
        &gen_op_##width##_kernel,                                        \
387
    };                                                                        \
388
                                                                        \
389
    static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
390
    {                                                                        \
391
        int asi, offset;                                                \
392
                                                                        \
393
        if (IS_IMM) {                                                        \
394
            offset = GET_FIELD(insn, 25, 31);                                \
395
            if (is_ld)                                                        \
396
                gen_op_ld_asi_reg(offset, size, sign);                        \
397
            else                                                        \
398
                gen_op_st_asi_reg(offset, size, sign);                        \
399
            return;                                                        \
400
        }                                                                \
401
        asi = GET_FIELD(insn, 19, 26);                                        \
402
        if (is_ld)                                                        \
403
            gen_op_ld_asi(asi, size, sign);                                \
404
        else                                                                \
405
            gen_op_st_asi(asi, size, sign);                                \
406
    }
407

    
408
#define supervisor(dc) (dc->mem_idx == 1)
409
#endif
410
#else
411
#if defined(CONFIG_USER_ONLY)
412
#define gen_op_ldst(name)        gen_op_##name##_raw()
413
#define OP_LD_TABLE(width)
414
#define supervisor(dc) 0
415
#else
416
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
417
#define OP_LD_TABLE(width)                                                      \
418
static GenOpFunc *gen_op_##width[] = {                                        \
419
    &gen_op_##width##_user,                                                   \
420
    &gen_op_##width##_kernel,                                                 \
421
};                                                                            \
422
                                                                              \
423
static void gen_op_##width##a(int insn, int is_ld, int size, int sign)        \
424
{                                                                             \
425
    int asi;                                                                  \
426
                                                                              \
427
    asi = GET_FIELD(insn, 19, 26);                                            \
428
    switch (asi) {                                                            \
429
        case 10: /* User data access */                                       \
430
            gen_op_##width##_user();                                          \
431
            break;                                                            \
432
        case 11: /* Supervisor data access */                                 \
433
            gen_op_##width##_kernel();                                        \
434
            break;                                                            \
435
        case 0x20 ... 0x2f: /* MMU passthrough */                              \
436
            if (is_ld)                                                        \
437
                gen_op_ld_asi(asi, size, sign);                                      \
438
            else                                                              \
439
                gen_op_st_asi(asi, size, sign);                                      \
440
            break;                                                            \
441
        default:                                                              \
442
            if (is_ld)                                                        \
443
                gen_op_ld_asi(asi, size, sign);                                      \
444
            else                                                              \
445
                gen_op_st_asi(asi, size, sign);                                      \
446
            break;                                                            \
447
    }                                                                         \
448
}
449

    
450
#define supervisor(dc) (dc->mem_idx == 1)
451
#endif
452
#endif
453

    
454
OP_LD_TABLE(ld);
455
OP_LD_TABLE(st);
456
OP_LD_TABLE(ldub);
457
OP_LD_TABLE(lduh);
458
OP_LD_TABLE(ldsb);
459
OP_LD_TABLE(ldsh);
460
OP_LD_TABLE(stb);
461
OP_LD_TABLE(sth);
462
OP_LD_TABLE(std);
463
OP_LD_TABLE(ldstub);
464
OP_LD_TABLE(swap);
465
OP_LD_TABLE(ldd);
466
OP_LD_TABLE(stf);
467
OP_LD_TABLE(stdf);
468
OP_LD_TABLE(ldf);
469
OP_LD_TABLE(lddf);
470

    
471
#ifdef TARGET_SPARC64
472
OP_LD_TABLE(ldsw);
473
OP_LD_TABLE(ldx);
474
OP_LD_TABLE(stx);
475
OP_LD_TABLE(cas);
476
OP_LD_TABLE(casx);
477
#endif
478

    
479
static inline void gen_movl_imm_TN(int reg, uint32_t imm)
480
{
481
    gen_op_movl_TN_im[reg](imm);
482
}
483

    
484
static inline void gen_movl_imm_T1(uint32_t val)
485
{
486
    gen_movl_imm_TN(1, val);
487
}
488

    
489
static inline void gen_movl_imm_T0(uint32_t val)
490
{
491
    gen_movl_imm_TN(0, val);
492
}
493

    
494
static inline void gen_movl_simm_TN(int reg, int32_t imm)
495
{
496
    gen_op_movl_TN_sim[reg](imm);
497
}
498

    
499
static inline void gen_movl_simm_T1(int32_t val)
500
{
501
    gen_movl_simm_TN(1, val);
502
}
503

    
504
static inline void gen_movl_simm_T0(int32_t val)
505
{
506
    gen_movl_simm_TN(0, val);
507
}
508

    
509
static inline void gen_movl_reg_TN(int reg, int t)
510
{
511
    if (reg)
512
        gen_op_movl_reg_TN[t][reg] ();
513
    else
514
        gen_movl_imm_TN(t, 0);
515
}
516

    
517
static inline void gen_movl_reg_T0(int reg)
518
{
519
    gen_movl_reg_TN(reg, 0);
520
}
521

    
522
static inline void gen_movl_reg_T1(int reg)
523
{
524
    gen_movl_reg_TN(reg, 1);
525
}
526

    
527
static inline void gen_movl_reg_T2(int reg)
528
{
529
    gen_movl_reg_TN(reg, 2);
530
}
531

    
532
static inline void gen_movl_TN_reg(int reg, int t)
533
{
534
    if (reg)
535
        gen_op_movl_TN_reg[t][reg] ();
536
}
537

    
538
static inline void gen_movl_T0_reg(int reg)
539
{
540
    gen_movl_TN_reg(reg, 0);
541
}
542

    
543
static inline void gen_movl_T1_reg(int reg)
544
{
545
    gen_movl_TN_reg(reg, 1);
546
}
547

    
548
static inline void gen_jmp_im(target_ulong pc)
549
{
550
#ifdef TARGET_SPARC64
551
    if (pc == (uint32_t)pc) {
552
        gen_op_jmp_im(pc);
553
    } else {
554
        gen_op_jmp_im64(pc >> 32, pc);
555
    }
556
#else
557
    gen_op_jmp_im(pc);
558
#endif
559
}
560

    
561
static inline void gen_movl_npc_im(target_ulong npc)
562
{
563
#ifdef TARGET_SPARC64
564
    if (npc == (uint32_t)npc) {
565
        gen_op_movl_npc_im(npc);
566
    } else {
567
        gen_op_movq_npc_im64(npc >> 32, npc);
568
    }
569
#else
570
    gen_op_movl_npc_im(npc);
571
#endif
572
}
573

    
574
static inline void gen_goto_tb(DisasContext *s, int tb_num, 
575
                               target_ulong pc, target_ulong npc)
576
{
577
    TranslationBlock *tb;
578

    
579
    tb = s->tb;
580
    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
581
        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK))  {
582
        /* jump to same page: we can use a direct jump */
583
        if (tb_num == 0)
584
            gen_op_goto_tb0(TBPARAM(tb));
585
        else
586
            gen_op_goto_tb1(TBPARAM(tb));
587
        gen_jmp_im(pc);
588
        gen_movl_npc_im(npc);
589
        gen_op_movl_T0_im((long)tb + tb_num);
590
        gen_op_exit_tb();
591
    } else {
592
        /* jump to another page: currently not optimized */
593
        gen_jmp_im(pc);
594
        gen_movl_npc_im(npc);
595
        gen_op_movl_T0_0();
596
        gen_op_exit_tb();
597
    }
598
}
599

    
600
static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
601
{
602
    int l1;
603

    
604
    l1 = gen_new_label();
605

    
606
    gen_op_jz_T2_label(l1);
607

    
608
    gen_goto_tb(dc, 0, pc1, pc1 + 4);
609

    
610
    gen_set_label(l1);
611
    gen_goto_tb(dc, 1, pc2, pc2 + 4);
612
}
613

    
614
static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
615
{
616
    int l1;
617

    
618
    l1 = gen_new_label();
619

    
620
    gen_op_jz_T2_label(l1);
621

    
622
    gen_goto_tb(dc, 0, pc2, pc1);
623

    
624
    gen_set_label(l1);
625
    gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
626
}
627

    
628
static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
629
{
630
    gen_goto_tb(dc, 0, pc, npc);
631
}
632

    
633
static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2)
634
{
635
    int l1, l2;
636

    
637
    l1 = gen_new_label();
638
    l2 = gen_new_label();
639
    gen_op_jz_T2_label(l1);
640

    
641
    gen_movl_npc_im(npc1);
642
    gen_op_jmp_label(l2);
643

    
644
    gen_set_label(l1);
645
    gen_movl_npc_im(npc2);
646
    gen_set_label(l2);
647
}
648

    
649
/* call this function before using T2 as it may have been set for a jump */
650
static inline void flush_T2(DisasContext * dc)
651
{
652
    if (dc->npc == JUMP_PC) {
653
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
654
        dc->npc = DYNAMIC_PC;
655
    }
656
}
657

    
658
static inline void save_npc(DisasContext * dc)
659
{
660
    if (dc->npc == JUMP_PC) {
661
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
662
        dc->npc = DYNAMIC_PC;
663
    } else if (dc->npc != DYNAMIC_PC) {
664
        gen_movl_npc_im(dc->npc);
665
    }
666
}
667

    
668
static inline void save_state(DisasContext * dc)
669
{
670
    gen_jmp_im(dc->pc);
671
    save_npc(dc);
672
}
673

    
674
static inline void gen_mov_pc_npc(DisasContext * dc)
675
{
676
    if (dc->npc == JUMP_PC) {
677
        gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
678
        gen_op_mov_pc_npc();
679
        dc->pc = DYNAMIC_PC;
680
    } else if (dc->npc == DYNAMIC_PC) {
681
        gen_op_mov_pc_npc();
682
        dc->pc = DYNAMIC_PC;
683
    } else {
684
        dc->pc = dc->npc;
685
    }
686
}
687

    
688
static GenOpFunc * const gen_cond[2][16] = {
689
    {
690
        gen_op_eval_bn,
691
        gen_op_eval_be,
692
        gen_op_eval_ble,
693
        gen_op_eval_bl,
694
        gen_op_eval_bleu,
695
        gen_op_eval_bcs,
696
        gen_op_eval_bneg,
697
        gen_op_eval_bvs,
698
        gen_op_eval_ba,
699
        gen_op_eval_bne,
700
        gen_op_eval_bg,
701
        gen_op_eval_bge,
702
        gen_op_eval_bgu,
703
        gen_op_eval_bcc,
704
        gen_op_eval_bpos,
705
        gen_op_eval_bvc,
706
    },
707
    {
708
#ifdef TARGET_SPARC64
709
        gen_op_eval_bn,
710
        gen_op_eval_xbe,
711
        gen_op_eval_xble,
712
        gen_op_eval_xbl,
713
        gen_op_eval_xbleu,
714
        gen_op_eval_xbcs,
715
        gen_op_eval_xbneg,
716
        gen_op_eval_xbvs,
717
        gen_op_eval_ba,
718
        gen_op_eval_xbne,
719
        gen_op_eval_xbg,
720
        gen_op_eval_xbge,
721
        gen_op_eval_xbgu,
722
        gen_op_eval_xbcc,
723
        gen_op_eval_xbpos,
724
        gen_op_eval_xbvc,
725
#endif
726
    },
727
};
728

    
729
static GenOpFunc * const gen_fcond[4][16] = {
730
    {
731
        gen_op_eval_bn,
732
        gen_op_eval_fbne,
733
        gen_op_eval_fblg,
734
        gen_op_eval_fbul,
735
        gen_op_eval_fbl,
736
        gen_op_eval_fbug,
737
        gen_op_eval_fbg,
738
        gen_op_eval_fbu,
739
        gen_op_eval_ba,
740
        gen_op_eval_fbe,
741
        gen_op_eval_fbue,
742
        gen_op_eval_fbge,
743
        gen_op_eval_fbuge,
744
        gen_op_eval_fble,
745
        gen_op_eval_fbule,
746
        gen_op_eval_fbo,
747
    },
748
#ifdef TARGET_SPARC64
749
    {
750
        gen_op_eval_bn,
751
        gen_op_eval_fbne_fcc1,
752
        gen_op_eval_fblg_fcc1,
753
        gen_op_eval_fbul_fcc1,
754
        gen_op_eval_fbl_fcc1,
755
        gen_op_eval_fbug_fcc1,
756
        gen_op_eval_fbg_fcc1,
757
        gen_op_eval_fbu_fcc1,
758
        gen_op_eval_ba,
759
        gen_op_eval_fbe_fcc1,
760
        gen_op_eval_fbue_fcc1,
761
        gen_op_eval_fbge_fcc1,
762
        gen_op_eval_fbuge_fcc1,
763
        gen_op_eval_fble_fcc1,
764
        gen_op_eval_fbule_fcc1,
765
        gen_op_eval_fbo_fcc1,
766
    },
767
    {
768
        gen_op_eval_bn,
769
        gen_op_eval_fbne_fcc2,
770
        gen_op_eval_fblg_fcc2,
771
        gen_op_eval_fbul_fcc2,
772
        gen_op_eval_fbl_fcc2,
773
        gen_op_eval_fbug_fcc2,
774
        gen_op_eval_fbg_fcc2,
775
        gen_op_eval_fbu_fcc2,
776
        gen_op_eval_ba,
777
        gen_op_eval_fbe_fcc2,
778
        gen_op_eval_fbue_fcc2,
779
        gen_op_eval_fbge_fcc2,
780
        gen_op_eval_fbuge_fcc2,
781
        gen_op_eval_fble_fcc2,
782
        gen_op_eval_fbule_fcc2,
783
        gen_op_eval_fbo_fcc2,
784
    },
785
    {
786
        gen_op_eval_bn,
787
        gen_op_eval_fbne_fcc3,
788
        gen_op_eval_fblg_fcc3,
789
        gen_op_eval_fbul_fcc3,
790
        gen_op_eval_fbl_fcc3,
791
        gen_op_eval_fbug_fcc3,
792
        gen_op_eval_fbg_fcc3,
793
        gen_op_eval_fbu_fcc3,
794
        gen_op_eval_ba,
795
        gen_op_eval_fbe_fcc3,
796
        gen_op_eval_fbue_fcc3,
797
        gen_op_eval_fbge_fcc3,
798
        gen_op_eval_fbuge_fcc3,
799
        gen_op_eval_fble_fcc3,
800
        gen_op_eval_fbule_fcc3,
801
        gen_op_eval_fbo_fcc3,
802
    },
803
#else
804
    {}, {}, {},
805
#endif
806
};
807

    
808
#ifdef TARGET_SPARC64
809
static void gen_cond_reg(int cond)
810
{
811
        switch (cond) {
812
        case 0x1:
813
            gen_op_eval_brz();
814
            break;
815
        case 0x2:
816
            gen_op_eval_brlez();
817
            break;
818
        case 0x3:
819
            gen_op_eval_brlz();
820
            break;
821
        case 0x5:
822
            gen_op_eval_brnz();
823
            break;
824
        case 0x6:
825
            gen_op_eval_brgz();
826
            break;
827
        default:
828
        case 0x7:
829
            gen_op_eval_brgez();
830
            break;
831
        }
832
}
833
#endif
834

    
835
/* XXX: potentially incorrect if dynamic npc */
836
static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
837
{
838
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
839
    target_ulong target = dc->pc + offset;
840
        
841
    if (cond == 0x0) {
842
        /* unconditional not taken */
843
        if (a) {
844
            dc->pc = dc->npc + 4; 
845
            dc->npc = dc->pc + 4;
846
        } else {
847
            dc->pc = dc->npc;
848
            dc->npc = dc->pc + 4;
849
        }
850
    } else if (cond == 0x8) {
851
        /* unconditional taken */
852
        if (a) {
853
            dc->pc = target;
854
            dc->npc = dc->pc + 4;
855
        } else {
856
            dc->pc = dc->npc;
857
            dc->npc = target;
858
        }
859
    } else {
860
        flush_T2(dc);
861
        gen_cond[cc][cond]();
862
        if (a) {
863
            gen_branch_a(dc, (long)dc->tb, target, dc->npc);
864
            dc->is_br = 1;
865
        } else {
866
            dc->pc = dc->npc;
867
            dc->jump_pc[0] = target;
868
            dc->jump_pc[1] = dc->npc + 4;
869
            dc->npc = JUMP_PC;
870
        }
871
    }
872
}
873

    
874
/* XXX: potentially incorrect if dynamic npc */
875
static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
876
{
877
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
878
    target_ulong target = dc->pc + offset;
879

    
880
    if (cond == 0x0) {
881
        /* unconditional not taken */
882
        if (a) {
883
            dc->pc = dc->npc + 4;
884
            dc->npc = dc->pc + 4;
885
        } else {
886
            dc->pc = dc->npc;
887
            dc->npc = dc->pc + 4;
888
        }
889
    } else if (cond == 0x8) {
890
        /* unconditional taken */
891
        if (a) {
892
            dc->pc = target;
893
            dc->npc = dc->pc + 4;
894
        } else {
895
            dc->pc = dc->npc;
896
            dc->npc = target;
897
        }
898
    } else {
899
        flush_T2(dc);
900
        gen_fcond[cc][cond]();
901
        if (a) {
902
            gen_branch_a(dc, (long)dc->tb, target, dc->npc);
903
            dc->is_br = 1;
904
        } else {
905
            dc->pc = dc->npc;
906
            dc->jump_pc[0] = target;
907
            dc->jump_pc[1] = dc->npc + 4;
908
            dc->npc = JUMP_PC;
909
        }
910
    }
911
}
912

    
913
#ifdef TARGET_SPARC64
914
/* XXX: potentially incorrect if dynamic npc */
915
static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
916
{
917
    unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
918
    target_ulong target = dc->pc + offset;
919

    
920
    flush_T2(dc);
921
    gen_cond_reg(cond);
922
    if (a) {
923
        gen_branch_a(dc, (long)dc->tb, target, dc->npc);
924
        dc->is_br = 1;
925
    } else {
926
        dc->pc = dc->npc;
927
        dc->jump_pc[0] = target;
928
        dc->jump_pc[1] = dc->npc + 4;
929
        dc->npc = JUMP_PC;
930
    }
931
}
932

    
933
static GenOpFunc * const gen_fcmps[4] = {
934
    gen_op_fcmps,
935
    gen_op_fcmps_fcc1,
936
    gen_op_fcmps_fcc2,
937
    gen_op_fcmps_fcc3,
938
};
939

    
940
static GenOpFunc * const gen_fcmpd[4] = {
941
    gen_op_fcmpd,
942
    gen_op_fcmpd_fcc1,
943
    gen_op_fcmpd_fcc2,
944
    gen_op_fcmpd_fcc3,
945
};
946
#endif
947

    
948
static int gen_trap_ifnofpu(DisasContext * dc)
949
{
950
#if !defined(CONFIG_USER_ONLY)
951
    if (!dc->fpu_enabled) {
952
        save_state(dc);
953
        gen_op_exception(TT_NFPU_INSN);
954
        dc->is_br = 1;
955
        return 1;
956
    }
957
#endif
958
    return 0;
959
}
960

    
961
/* before an instruction, dc->pc must be static */
962
static void disas_sparc_insn(DisasContext * dc)
963
{
964
    unsigned int insn, opc, rs1, rs2, rd;
965

    
966
    insn = ldl_code(dc->pc);
967
    opc = GET_FIELD(insn, 0, 1);
968

    
969
    rd = GET_FIELD(insn, 2, 6);
970
    switch (opc) {
971
    case 0:                        /* branches/sethi */
972
        {
973
            unsigned int xop = GET_FIELD(insn, 7, 9);
974
            int32_t target;
975
            switch (xop) {
976
#ifdef TARGET_SPARC64
977
            case 0x1:                /* V9 BPcc */
978
                {
979
                    int cc;
980

    
981
                    target = GET_FIELD_SP(insn, 0, 18);
982
                    target = sign_extend(target, 18);
983
                    target <<= 2;
984
                    cc = GET_FIELD_SP(insn, 20, 21);
985
                    if (cc == 0)
986
                        do_branch(dc, target, insn, 0);
987
                    else if (cc == 2)
988
                        do_branch(dc, target, insn, 1);
989
                    else
990
                        goto illegal_insn;
991
                    goto jmp_insn;
992
                }
993
            case 0x3:                /* V9 BPr */
994
                {
995
                    target = GET_FIELD_SP(insn, 0, 13) | 
996
                        (GET_FIELD_SP(insn, 20, 21) << 14);
997
                    target = sign_extend(target, 16);
998
                    target <<= 2;
999
                    rs1 = GET_FIELD(insn, 13, 17);
1000
                    gen_movl_reg_T0(rs1);
1001
                    do_branch_reg(dc, target, insn);
1002
                    goto jmp_insn;
1003
                }
1004
            case 0x5:                /* V9 FBPcc */
1005
                {
1006
                    int cc = GET_FIELD_SP(insn, 20, 21);
1007
                    if (gen_trap_ifnofpu(dc))
1008
                        goto jmp_insn;
1009
                    target = GET_FIELD_SP(insn, 0, 18);
1010
                    target = sign_extend(target, 19);
1011
                    target <<= 2;
1012
                    do_fbranch(dc, target, insn, cc);
1013
                    goto jmp_insn;
1014
                }
1015
#else
1016
            case 0x7:                /* CBN+x */
1017
                {
1018
                    goto ncp_insn;
1019
                }
1020
#endif
1021
            case 0x2:                /* BN+x */
1022
                {
1023
                    target = GET_FIELD(insn, 10, 31);
1024
                    target = sign_extend(target, 22);
1025
                    target <<= 2;
1026
                    do_branch(dc, target, insn, 0);
1027
                    goto jmp_insn;
1028
                }
1029
            case 0x6:                /* FBN+x */
1030
                {
1031
                    if (gen_trap_ifnofpu(dc))
1032
                        goto jmp_insn;
1033
                    target = GET_FIELD(insn, 10, 31);
1034
                    target = sign_extend(target, 22);
1035
                    target <<= 2;
1036
                    do_fbranch(dc, target, insn, 0);
1037
                    goto jmp_insn;
1038
                }
1039
            case 0x4:                /* SETHI */
1040
#define OPTIM
1041
#if defined(OPTIM)
1042
                if (rd) { // nop
1043
#endif
1044
                    uint32_t value = GET_FIELD(insn, 10, 31);
1045
                    gen_movl_imm_T0(value << 10);
1046
                    gen_movl_T0_reg(rd);
1047
#if defined(OPTIM)
1048
                }
1049
#endif
1050
                break;
1051
            case 0x0:                /* UNIMPL */
1052
            default:
1053
                goto illegal_insn;
1054
            }
1055
            break;
1056
        }
1057
        break;
1058
    case 1:
1059
        /*CALL*/ {
1060
            target_long target = GET_FIELDs(insn, 2, 31) << 2;
1061

    
1062
#ifdef TARGET_SPARC64
1063
            if (dc->pc == (uint32_t)dc->pc) {
1064
                gen_op_movl_T0_im(dc->pc);
1065
            } else {
1066
                gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1067
            }
1068
#else
1069
            gen_op_movl_T0_im(dc->pc);
1070
#endif
1071
            gen_movl_T0_reg(15);
1072
            target += dc->pc;
1073
            gen_mov_pc_npc(dc);
1074
            dc->npc = target;
1075
        }
1076
        goto jmp_insn;
1077
    case 2:                        /* FPU & Logical Operations */
1078
        {
1079
            unsigned int xop = GET_FIELD(insn, 7, 12);
1080
            if (xop == 0x3a) {        /* generate trap */
1081
                int cond;
1082

    
1083
                rs1 = GET_FIELD(insn, 13, 17);
1084
                gen_movl_reg_T0(rs1);
1085
                if (IS_IMM) {
1086
                    rs2 = GET_FIELD(insn, 25, 31);
1087
#if defined(OPTIM)
1088
                    if (rs2 != 0) {
1089
#endif
1090
                        gen_movl_simm_T1(rs2);
1091
                        gen_op_add_T1_T0();
1092
#if defined(OPTIM)
1093
                    }
1094
#endif
1095
                } else {
1096
                    rs2 = GET_FIELD(insn, 27, 31);
1097
#if defined(OPTIM)
1098
                    if (rs2 != 0) {
1099
#endif
1100
                        gen_movl_reg_T1(rs2);
1101
                        gen_op_add_T1_T0();
1102
#if defined(OPTIM)
1103
                    }
1104
#endif
1105
                }
1106
                cond = GET_FIELD(insn, 3, 6);
1107
                if (cond == 0x8) {
1108
                    save_state(dc);
1109
                    gen_op_trap_T0();
1110
                } else if (cond != 0) {
1111
#ifdef TARGET_SPARC64
1112
                    /* V9 icc/xcc */
1113
                    int cc = GET_FIELD_SP(insn, 11, 12);
1114
                    flush_T2(dc);
1115
                    save_state(dc);
1116
                    if (cc == 0)
1117
                        gen_cond[0][cond]();
1118
                    else if (cc == 2)
1119
                        gen_cond[1][cond]();
1120
                    else
1121
                        goto illegal_insn;
1122
#else
1123
                    flush_T2(dc);
1124
                    save_state(dc);
1125
                    gen_cond[0][cond]();
1126
#endif
1127
                    gen_op_trapcc_T0();
1128
                }
1129
                gen_op_next_insn();
1130
                gen_op_movl_T0_0();
1131
                gen_op_exit_tb();
1132
                dc->is_br = 1;
1133
                goto jmp_insn;
1134
            } else if (xop == 0x28) {
1135
                rs1 = GET_FIELD(insn, 13, 17);
1136
                switch(rs1) {
1137
                case 0: /* rdy */
1138
#ifndef TARGET_SPARC64
1139
                case 0x01 ... 0x0e: /* undefined in the SPARCv8
1140
                                       manual, rdy on the microSPARC
1141
                                       II */
1142
                case 0x0f:          /* stbar in the SPARCv8 manual,
1143
                                       rdy on the microSPARC II */
1144
                case 0x10 ... 0x1f: /* implementation-dependent in the
1145
                                       SPARCv8 manual, rdy on the
1146
                                       microSPARC II */
1147
#endif
1148
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
1149
                    gen_movl_T0_reg(rd);
1150
                    break;
1151
#ifdef TARGET_SPARC64
1152
                case 0x2: /* V9 rdccr */
1153
                    gen_op_rdccr();
1154
                    gen_movl_T0_reg(rd);
1155
                    break;
1156
                case 0x3: /* V9 rdasi */
1157
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
1158
                    gen_movl_T0_reg(rd);
1159
                    break;
1160
                case 0x4: /* V9 rdtick */
1161
                    gen_op_rdtick();
1162
                    gen_movl_T0_reg(rd);
1163
                    break;
1164
                case 0x5: /* V9 rdpc */
1165
                    if (dc->pc == (uint32_t)dc->pc) {
1166
                        gen_op_movl_T0_im(dc->pc);
1167
                    } else {
1168
                        gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1169
                    }
1170
                    gen_movl_T0_reg(rd);
1171
                    break;
1172
                case 0x6: /* V9 rdfprs */
1173
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
1174
                    gen_movl_T0_reg(rd);
1175
                    break;
1176
                case 0xf: /* V9 membar */
1177
                    break; /* no effect */
1178
                case 0x13: /* Graphics Status */
1179
                    if (gen_trap_ifnofpu(dc))
1180
                        goto jmp_insn;
1181
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
1182
                    gen_movl_T0_reg(rd);
1183
                    break;
1184
                case 0x17: /* Tick compare */
1185
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
1186
                    gen_movl_T0_reg(rd);
1187
                    break;
1188
                case 0x18: /* System tick */
1189
                    gen_op_rdtick(); // XXX
1190
                    gen_movl_T0_reg(rd);
1191
                    break;
1192
                case 0x19: /* System tick compare */
1193
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
1194
                    gen_movl_T0_reg(rd);
1195
                    break;
1196
                case 0x10: /* Performance Control */
1197
                case 0x11: /* Performance Instrumentation Counter */
1198
                case 0x12: /* Dispatch Control */
1199
                case 0x14: /* Softint set, WO */
1200
                case 0x15: /* Softint clear, WO */
1201
                case 0x16: /* Softint write */
1202
#endif
1203
                default:
1204
                    goto illegal_insn;
1205
                }
1206
#if !defined(CONFIG_USER_ONLY)
1207
#ifndef TARGET_SPARC64
1208
            } else if (xop == 0x29) { /* rdpsr / V9 unimp */
1209
                if (!supervisor(dc))
1210
                    goto priv_insn;
1211
                gen_op_rdpsr();
1212
                gen_movl_T0_reg(rd);
1213
                break;
1214
#endif
1215
            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1216
                if (!supervisor(dc))
1217
                    goto priv_insn;
1218
#ifdef TARGET_SPARC64
1219
                rs1 = GET_FIELD(insn, 13, 17);
1220
                switch (rs1) {
1221
                case 0: // tpc
1222
                    gen_op_rdtpc();
1223
                    break;
1224
                case 1: // tnpc
1225
                    gen_op_rdtnpc();
1226
                    break;
1227
                case 2: // tstate
1228
                    gen_op_rdtstate();
1229
                    break;
1230
                case 3: // tt
1231
                    gen_op_rdtt();
1232
                    break;
1233
                case 4: // tick
1234
                    gen_op_rdtick();
1235
                    break;
1236
                case 5: // tba
1237
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1238
                    break;
1239
                case 6: // pstate
1240
                    gen_op_rdpstate();
1241
                    break;
1242
                case 7: // tl
1243
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
1244
                    break;
1245
                case 8: // pil
1246
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
1247
                    break;
1248
                case 9: // cwp
1249
                    gen_op_rdcwp();
1250
                    break;
1251
                case 10: // cansave
1252
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
1253
                    break;
1254
                case 11: // canrestore
1255
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
1256
                    break;
1257
                case 12: // cleanwin
1258
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
1259
                    break;
1260
                case 13: // otherwin
1261
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
1262
                    break;
1263
                case 14: // wstate
1264
                    gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
1265
                    break;
1266
                case 31: // ver
1267
                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
1268
                    break;
1269
                case 15: // fq
1270
                default:
1271
                    goto illegal_insn;
1272
                }
1273
#else
1274
                gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
1275
#endif
1276
                gen_movl_T0_reg(rd);
1277
                break;
1278
            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
1279
#ifdef TARGET_SPARC64
1280
                gen_op_flushw();
1281
#else
1282
                if (!supervisor(dc))
1283
                    goto priv_insn;
1284
                gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1285
                gen_movl_T0_reg(rd);
1286
#endif
1287
                break;
1288
#endif
1289
            } else if (xop == 0x34) {        /* FPU Operations */
1290
                if (gen_trap_ifnofpu(dc))
1291
                    goto jmp_insn;
1292
                rs1 = GET_FIELD(insn, 13, 17);
1293
                rs2 = GET_FIELD(insn, 27, 31);
1294
                xop = GET_FIELD(insn, 18, 26);
1295
                switch (xop) {
1296
                    case 0x1: /* fmovs */
1297
                        gen_op_load_fpr_FT0(rs2);
1298
                        gen_op_store_FT0_fpr(rd);
1299
                        break;
1300
                    case 0x5: /* fnegs */
1301
                        gen_op_load_fpr_FT1(rs2);
1302
                        gen_op_fnegs();
1303
                        gen_op_store_FT0_fpr(rd);
1304
                        break;
1305
                    case 0x9: /* fabss */
1306
                        gen_op_load_fpr_FT1(rs2);
1307
                        gen_op_fabss();
1308
                        gen_op_store_FT0_fpr(rd);
1309
                        break;
1310
                    case 0x29: /* fsqrts */
1311
                        gen_op_load_fpr_FT1(rs2);
1312
                        gen_op_fsqrts();
1313
                        gen_op_store_FT0_fpr(rd);
1314
                        break;
1315
                    case 0x2a: /* fsqrtd */
1316
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1317
                        gen_op_fsqrtd();
1318
                        gen_op_store_DT0_fpr(DFPREG(rd));
1319
                        break;
1320
                    case 0x2b: /* fsqrtq */
1321
                        goto nfpu_insn;
1322
                    case 0x41:
1323
                        gen_op_load_fpr_FT0(rs1);
1324
                        gen_op_load_fpr_FT1(rs2);
1325
                        gen_op_fadds();
1326
                        gen_op_store_FT0_fpr(rd);
1327
                        break;
1328
                    case 0x42:
1329
                        gen_op_load_fpr_DT0(DFPREG(rs1));
1330
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1331
                        gen_op_faddd();
1332
                        gen_op_store_DT0_fpr(DFPREG(rd));
1333
                        break;
1334
                    case 0x43: /* faddq */
1335
                        goto nfpu_insn;
1336
                    case 0x45:
1337
                        gen_op_load_fpr_FT0(rs1);
1338
                        gen_op_load_fpr_FT1(rs2);
1339
                        gen_op_fsubs();
1340
                        gen_op_store_FT0_fpr(rd);
1341
                        break;
1342
                    case 0x46:
1343
                        gen_op_load_fpr_DT0(DFPREG(rs1));
1344
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1345
                        gen_op_fsubd();
1346
                        gen_op_store_DT0_fpr(DFPREG(rd));
1347
                        break;
1348
                    case 0x47: /* fsubq */
1349
                        goto nfpu_insn;
1350
                    case 0x49:
1351
                        gen_op_load_fpr_FT0(rs1);
1352
                        gen_op_load_fpr_FT1(rs2);
1353
                        gen_op_fmuls();
1354
                        gen_op_store_FT0_fpr(rd);
1355
                        break;
1356
                    case 0x4a:
1357
                        gen_op_load_fpr_DT0(DFPREG(rs1));
1358
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1359
                        gen_op_fmuld();
1360
                        gen_op_store_DT0_fpr(rd);
1361
                        break;
1362
                    case 0x4b: /* fmulq */
1363
                        goto nfpu_insn;
1364
                    case 0x4d:
1365
                        gen_op_load_fpr_FT0(rs1);
1366
                        gen_op_load_fpr_FT1(rs2);
1367
                        gen_op_fdivs();
1368
                        gen_op_store_FT0_fpr(rd);
1369
                        break;
1370
                    case 0x4e:
1371
                        gen_op_load_fpr_DT0(DFPREG(rs1));
1372
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1373
                        gen_op_fdivd();
1374
                        gen_op_store_DT0_fpr(DFPREG(rd));
1375
                        break;
1376
                    case 0x4f: /* fdivq */
1377
                        goto nfpu_insn;
1378
                    case 0x69:
1379
                        gen_op_load_fpr_FT0(rs1);
1380
                        gen_op_load_fpr_FT1(rs2);
1381
                        gen_op_fsmuld();
1382
                        gen_op_store_DT0_fpr(DFPREG(rd));
1383
                        break;
1384
                    case 0x6e: /* fdmulq */
1385
                        goto nfpu_insn;
1386
                    case 0xc4:
1387
                        gen_op_load_fpr_FT1(rs2);
1388
                        gen_op_fitos();
1389
                        gen_op_store_FT0_fpr(rd);
1390
                        break;
1391
                    case 0xc6:
1392
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1393
                        gen_op_fdtos();
1394
                        gen_op_store_FT0_fpr(rd);
1395
                        break;
1396
                    case 0xc7: /* fqtos */
1397
                        goto nfpu_insn;
1398
                    case 0xc8:
1399
                        gen_op_load_fpr_FT1(rs2);
1400
                        gen_op_fitod();
1401
                        gen_op_store_DT0_fpr(DFPREG(rd));
1402
                        break;
1403
                    case 0xc9:
1404
                        gen_op_load_fpr_FT1(rs2);
1405
                        gen_op_fstod();
1406
                        gen_op_store_DT0_fpr(DFPREG(rd));
1407
                        break;
1408
                    case 0xcb: /* fqtod */
1409
                        goto nfpu_insn;
1410
                    case 0xcc: /* fitoq */
1411
                        goto nfpu_insn;
1412
                    case 0xcd: /* fstoq */
1413
                        goto nfpu_insn;
1414
                    case 0xce: /* fdtoq */
1415
                        goto nfpu_insn;
1416
                    case 0xd1:
1417
                        gen_op_load_fpr_FT1(rs2);
1418
                        gen_op_fstoi();
1419
                        gen_op_store_FT0_fpr(rd);
1420
                        break;
1421
                    case 0xd2:
1422
                        gen_op_load_fpr_DT1(rs2);
1423
                        gen_op_fdtoi();
1424
                        gen_op_store_FT0_fpr(rd);
1425
                        break;
1426
                    case 0xd3: /* fqtoi */
1427
                        goto nfpu_insn;
1428
#ifdef TARGET_SPARC64
1429
                    case 0x2: /* V9 fmovd */
1430
                        gen_op_load_fpr_DT0(DFPREG(rs2));
1431
                        gen_op_store_DT0_fpr(DFPREG(rd));
1432
                        break;
1433
                    case 0x6: /* V9 fnegd */
1434
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1435
                        gen_op_fnegd();
1436
                        gen_op_store_DT0_fpr(DFPREG(rd));
1437
                        break;
1438
                    case 0xa: /* V9 fabsd */
1439
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1440
                        gen_op_fabsd();
1441
                        gen_op_store_DT0_fpr(DFPREG(rd));
1442
                        break;
1443
                    case 0x81: /* V9 fstox */
1444
                        gen_op_load_fpr_FT1(rs2);
1445
                        gen_op_fstox();
1446
                        gen_op_store_DT0_fpr(DFPREG(rd));
1447
                        break;
1448
                    case 0x82: /* V9 fdtox */
1449
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1450
                        gen_op_fdtox();
1451
                        gen_op_store_DT0_fpr(DFPREG(rd));
1452
                        break;
1453
                    case 0x84: /* V9 fxtos */
1454
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1455
                        gen_op_fxtos();
1456
                        gen_op_store_FT0_fpr(rd);
1457
                        break;
1458
                    case 0x88: /* V9 fxtod */
1459
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1460
                        gen_op_fxtod();
1461
                        gen_op_store_DT0_fpr(DFPREG(rd));
1462
                        break;
1463
                    case 0x3: /* V9 fmovq */
1464
                    case 0x7: /* V9 fnegq */
1465
                    case 0xb: /* V9 fabsq */
1466
                    case 0x83: /* V9 fqtox */
1467
                    case 0x8c: /* V9 fxtoq */
1468
                        goto nfpu_insn;
1469
#endif
1470
                    default:
1471
                        goto illegal_insn;
1472
                }
1473
            } else if (xop == 0x35) {        /* FPU Operations */
1474
#ifdef TARGET_SPARC64
1475
                int cond;
1476
#endif
1477
                if (gen_trap_ifnofpu(dc))
1478
                    goto jmp_insn;
1479
                rs1 = GET_FIELD(insn, 13, 17);
1480
                rs2 = GET_FIELD(insn, 27, 31);
1481
                xop = GET_FIELD(insn, 18, 26);
1482
#ifdef TARGET_SPARC64
1483
                if ((xop & 0x11f) == 0x005) { // V9 fmovsr
1484
                    cond = GET_FIELD_SP(insn, 14, 17);
1485
                    gen_op_load_fpr_FT0(rd);
1486
                    gen_op_load_fpr_FT1(rs2);
1487
                    rs1 = GET_FIELD(insn, 13, 17);
1488
                    gen_movl_reg_T0(rs1);
1489
                    flush_T2(dc);
1490
                    gen_cond_reg(cond);
1491
                    gen_op_fmovs_cc();
1492
                    gen_op_store_FT0_fpr(rd);
1493
                    break;
1494
                } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
1495
                    cond = GET_FIELD_SP(insn, 14, 17);
1496
                    gen_op_load_fpr_DT0(rd);
1497
                    gen_op_load_fpr_DT1(rs2);
1498
                    flush_T2(dc);
1499
                    rs1 = GET_FIELD(insn, 13, 17);
1500
                    gen_movl_reg_T0(rs1);
1501
                    gen_cond_reg(cond);
1502
                    gen_op_fmovs_cc();
1503
                    gen_op_store_DT0_fpr(rd);
1504
                    break;
1505
                } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
1506
                    goto nfpu_insn;
1507
                }
1508
#endif
1509
                switch (xop) {
1510
#ifdef TARGET_SPARC64
1511
                    case 0x001: /* V9 fmovscc %fcc0 */
1512
                        cond = GET_FIELD_SP(insn, 14, 17);
1513
                        gen_op_load_fpr_FT0(rd);
1514
                        gen_op_load_fpr_FT1(rs2);
1515
                        flush_T2(dc);
1516
                        gen_fcond[0][cond]();
1517
                        gen_op_fmovs_cc();
1518
                        gen_op_store_FT0_fpr(rd);
1519
                        break;
1520
                    case 0x002: /* V9 fmovdcc %fcc0 */
1521
                        cond = GET_FIELD_SP(insn, 14, 17);
1522
                        gen_op_load_fpr_DT0(rd);
1523
                        gen_op_load_fpr_DT1(rs2);
1524
                        flush_T2(dc);
1525
                        gen_fcond[0][cond]();
1526
                        gen_op_fmovd_cc();
1527
                        gen_op_store_DT0_fpr(rd);
1528
                        break;
1529
                    case 0x003: /* V9 fmovqcc %fcc0 */
1530
                        goto nfpu_insn;
1531
                    case 0x041: /* V9 fmovscc %fcc1 */
1532
                        cond = GET_FIELD_SP(insn, 14, 17);
1533
                        gen_op_load_fpr_FT0(rd);
1534
                        gen_op_load_fpr_FT1(rs2);
1535
                        flush_T2(dc);
1536
                        gen_fcond[1][cond]();
1537
                        gen_op_fmovs_cc();
1538
                        gen_op_store_FT0_fpr(rd);
1539
                        break;
1540
                    case 0x042: /* V9 fmovdcc %fcc1 */
1541
                        cond = GET_FIELD_SP(insn, 14, 17);
1542
                        gen_op_load_fpr_DT0(rd);
1543
                        gen_op_load_fpr_DT1(rs2);
1544
                        flush_T2(dc);
1545
                        gen_fcond[1][cond]();
1546
                        gen_op_fmovd_cc();
1547
                        gen_op_store_DT0_fpr(rd);
1548
                        break;
1549
                    case 0x043: /* V9 fmovqcc %fcc1 */
1550
                        goto nfpu_insn;
1551
                    case 0x081: /* V9 fmovscc %fcc2 */
1552
                        cond = GET_FIELD_SP(insn, 14, 17);
1553
                        gen_op_load_fpr_FT0(rd);
1554
                        gen_op_load_fpr_FT1(rs2);
1555
                        flush_T2(dc);
1556
                        gen_fcond[2][cond]();
1557
                        gen_op_fmovs_cc();
1558
                        gen_op_store_FT0_fpr(rd);
1559
                        break;
1560
                    case 0x082: /* V9 fmovdcc %fcc2 */
1561
                        cond = GET_FIELD_SP(insn, 14, 17);
1562
                        gen_op_load_fpr_DT0(rd);
1563
                        gen_op_load_fpr_DT1(rs2);
1564
                        flush_T2(dc);
1565
                        gen_fcond[2][cond]();
1566
                        gen_op_fmovd_cc();
1567
                        gen_op_store_DT0_fpr(rd);
1568
                        break;
1569
                    case 0x083: /* V9 fmovqcc %fcc2 */
1570
                        goto nfpu_insn;
1571
                    case 0x0c1: /* V9 fmovscc %fcc3 */
1572
                        cond = GET_FIELD_SP(insn, 14, 17);
1573
                        gen_op_load_fpr_FT0(rd);
1574
                        gen_op_load_fpr_FT1(rs2);
1575
                        flush_T2(dc);
1576
                        gen_fcond[3][cond]();
1577
                        gen_op_fmovs_cc();
1578
                        gen_op_store_FT0_fpr(rd);
1579
                        break;
1580
                    case 0x0c2: /* V9 fmovdcc %fcc3 */
1581
                        cond = GET_FIELD_SP(insn, 14, 17);
1582
                        gen_op_load_fpr_DT0(rd);
1583
                        gen_op_load_fpr_DT1(rs2);
1584
                        flush_T2(dc);
1585
                        gen_fcond[3][cond]();
1586
                        gen_op_fmovd_cc();
1587
                        gen_op_store_DT0_fpr(rd);
1588
                        break;
1589
                    case 0x0c3: /* V9 fmovqcc %fcc3 */
1590
                        goto nfpu_insn;
1591
                    case 0x101: /* V9 fmovscc %icc */
1592
                        cond = GET_FIELD_SP(insn, 14, 17);
1593
                        gen_op_load_fpr_FT0(rd);
1594
                        gen_op_load_fpr_FT1(rs2);
1595
                        flush_T2(dc);
1596
                        gen_cond[0][cond]();
1597
                        gen_op_fmovs_cc();
1598
                        gen_op_store_FT0_fpr(rd);
1599
                        break;
1600
                    case 0x102: /* V9 fmovdcc %icc */
1601
                        cond = GET_FIELD_SP(insn, 14, 17);
1602
                        gen_op_load_fpr_DT0(rd);
1603
                        gen_op_load_fpr_DT1(rs2);
1604
                        flush_T2(dc);
1605
                        gen_cond[0][cond]();
1606
                        gen_op_fmovd_cc();
1607
                        gen_op_store_DT0_fpr(rd);
1608
                        break;
1609
                    case 0x103: /* V9 fmovqcc %icc */
1610
                        goto nfpu_insn;
1611
                    case 0x181: /* V9 fmovscc %xcc */
1612
                        cond = GET_FIELD_SP(insn, 14, 17);
1613
                        gen_op_load_fpr_FT0(rd);
1614
                        gen_op_load_fpr_FT1(rs2);
1615
                        flush_T2(dc);
1616
                        gen_cond[1][cond]();
1617
                        gen_op_fmovs_cc();
1618
                        gen_op_store_FT0_fpr(rd);
1619
                        break;
1620
                    case 0x182: /* V9 fmovdcc %xcc */
1621
                        cond = GET_FIELD_SP(insn, 14, 17);
1622
                        gen_op_load_fpr_DT0(rd);
1623
                        gen_op_load_fpr_DT1(rs2);
1624
                        flush_T2(dc);
1625
                        gen_cond[1][cond]();
1626
                        gen_op_fmovd_cc();
1627
                        gen_op_store_DT0_fpr(rd);
1628
                        break;
1629
                    case 0x183: /* V9 fmovqcc %xcc */
1630
                        goto nfpu_insn;
1631
#endif
1632
                    case 0x51: /* V9 %fcc */
1633
                        gen_op_load_fpr_FT0(rs1);
1634
                        gen_op_load_fpr_FT1(rs2);
1635
#ifdef TARGET_SPARC64
1636
                        gen_fcmps[rd & 3]();
1637
#else
1638
                        gen_op_fcmps();
1639
#endif
1640
                        break;
1641
                    case 0x52: /* V9 %fcc */
1642
                        gen_op_load_fpr_DT0(DFPREG(rs1));
1643
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1644
#ifdef TARGET_SPARC64
1645
                        gen_fcmpd[rd & 3]();
1646
#else
1647
                        gen_op_fcmpd();
1648
#endif
1649
                        break;
1650
                    case 0x53: /* fcmpq */
1651
                        goto nfpu_insn;
1652
                    case 0x55: /* fcmpes, V9 %fcc */
1653
                        gen_op_load_fpr_FT0(rs1);
1654
                        gen_op_load_fpr_FT1(rs2);
1655
#ifdef TARGET_SPARC64
1656
                        gen_fcmps[rd & 3]();
1657
#else
1658
                        gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */
1659
#endif
1660
                        break;
1661
                    case 0x56: /* fcmped, V9 %fcc */
1662
                        gen_op_load_fpr_DT0(DFPREG(rs1));
1663
                        gen_op_load_fpr_DT1(DFPREG(rs2));
1664
#ifdef TARGET_SPARC64
1665
                        gen_fcmpd[rd & 3]();
1666
#else
1667
                        gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */
1668
#endif
1669
                        break;
1670
                    case 0x57: /* fcmpeq */
1671
                        goto nfpu_insn;
1672
                    default:
1673
                        goto illegal_insn;
1674
                }
1675
#if defined(OPTIM)
1676
            } else if (xop == 0x2) {
1677
                // clr/mov shortcut
1678

    
1679
                rs1 = GET_FIELD(insn, 13, 17);
1680
                if (rs1 == 0) {
1681
                    // or %g0, x, y -> mov T1, x; mov y, T1
1682
                    if (IS_IMM) {        /* immediate */
1683
                        rs2 = GET_FIELDs(insn, 19, 31);
1684
                        gen_movl_simm_T1(rs2);
1685
                    } else {                /* register */
1686
                        rs2 = GET_FIELD(insn, 27, 31);
1687
                        gen_movl_reg_T1(rs2);
1688
                    }
1689
                    gen_movl_T1_reg(rd);
1690
                } else {
1691
                    gen_movl_reg_T0(rs1);
1692
                    if (IS_IMM) {        /* immediate */
1693
                        // or x, #0, y -> mov T1, x; mov y, T1
1694
                        rs2 = GET_FIELDs(insn, 19, 31);
1695
                        if (rs2 != 0) {
1696
                            gen_movl_simm_T1(rs2);
1697
                            gen_op_or_T1_T0();
1698
                        }
1699
                    } else {                /* register */
1700
                        // or x, %g0, y -> mov T1, x; mov y, T1
1701
                        rs2 = GET_FIELD(insn, 27, 31);
1702
                        if (rs2 != 0) {
1703
                            gen_movl_reg_T1(rs2);
1704
                            gen_op_or_T1_T0();
1705
                        }
1706
                    }
1707
                    gen_movl_T0_reg(rd);
1708
                }
1709
#endif
1710
#ifdef TARGET_SPARC64
1711
            } else if (xop == 0x25) { /* sll, V9 sllx */
1712
                rs1 = GET_FIELD(insn, 13, 17);
1713
                gen_movl_reg_T0(rs1);
1714
                if (IS_IMM) {        /* immediate */
1715
                    rs2 = GET_FIELDs(insn, 20, 31);
1716
                    gen_movl_simm_T1(rs2);
1717
                } else {                /* register */
1718
                    rs2 = GET_FIELD(insn, 27, 31);
1719
                    gen_movl_reg_T1(rs2);
1720
                }
1721
                if (insn & (1 << 12))
1722
                    gen_op_sllx();
1723
                else
1724
                    gen_op_sll();
1725
                gen_movl_T0_reg(rd);
1726
            } else if (xop == 0x26) { /* srl, V9 srlx */
1727
                rs1 = GET_FIELD(insn, 13, 17);
1728
                gen_movl_reg_T0(rs1);
1729
                if (IS_IMM) {        /* immediate */
1730
                    rs2 = GET_FIELDs(insn, 20, 31);
1731
                    gen_movl_simm_T1(rs2);
1732
                } else {                /* register */
1733
                    rs2 = GET_FIELD(insn, 27, 31);
1734
                    gen_movl_reg_T1(rs2);
1735
                }
1736
                if (insn & (1 << 12))
1737
                    gen_op_srlx();
1738
                else
1739
                    gen_op_srl();
1740
                gen_movl_T0_reg(rd);
1741
            } else if (xop == 0x27) { /* sra, V9 srax */
1742
                rs1 = GET_FIELD(insn, 13, 17);
1743
                gen_movl_reg_T0(rs1);
1744
                if (IS_IMM) {        /* immediate */
1745
                    rs2 = GET_FIELDs(insn, 20, 31);
1746
                    gen_movl_simm_T1(rs2);
1747
                } else {                /* register */
1748
                    rs2 = GET_FIELD(insn, 27, 31);
1749
                    gen_movl_reg_T1(rs2);
1750
                }
1751
                if (insn & (1 << 12))
1752
                    gen_op_srax();
1753
                else
1754
                    gen_op_sra();
1755
                gen_movl_T0_reg(rd);
1756
#endif
1757
            } else if (xop < 0x36) {
1758
                rs1 = GET_FIELD(insn, 13, 17);
1759
                gen_movl_reg_T0(rs1);
1760
                if (IS_IMM) {        /* immediate */
1761
                    rs2 = GET_FIELDs(insn, 19, 31);
1762
                    gen_movl_simm_T1(rs2);
1763
                } else {                /* register */
1764
                    rs2 = GET_FIELD(insn, 27, 31);
1765
                    gen_movl_reg_T1(rs2);
1766
                }
1767
                if (xop < 0x20) {
1768
                    switch (xop & ~0x10) {
1769
                    case 0x0:
1770
                        if (xop & 0x10)
1771
                            gen_op_add_T1_T0_cc();
1772
                        else
1773
                            gen_op_add_T1_T0();
1774
                        break;
1775
                    case 0x1:
1776
                        gen_op_and_T1_T0();
1777
                        if (xop & 0x10)
1778
                            gen_op_logic_T0_cc();
1779
                        break;
1780
                    case 0x2:
1781
                        gen_op_or_T1_T0();
1782
                        if (xop & 0x10)
1783
                            gen_op_logic_T0_cc();
1784
                        break;
1785
                    case 0x3:
1786
                        gen_op_xor_T1_T0();
1787
                        if (xop & 0x10)
1788
                            gen_op_logic_T0_cc();
1789
                        break;
1790
                    case 0x4:
1791
                        if (xop & 0x10)
1792
                            gen_op_sub_T1_T0_cc();
1793
                        else
1794
                            gen_op_sub_T1_T0();
1795
                        break;
1796
                    case 0x5:
1797
                        gen_op_andn_T1_T0();
1798
                        if (xop & 0x10)
1799
                            gen_op_logic_T0_cc();
1800
                        break;
1801
                    case 0x6:
1802
                        gen_op_orn_T1_T0();
1803
                        if (xop & 0x10)
1804
                            gen_op_logic_T0_cc();
1805
                        break;
1806
                    case 0x7:
1807
                        gen_op_xnor_T1_T0();
1808
                        if (xop & 0x10)
1809
                            gen_op_logic_T0_cc();
1810
                        break;
1811
                    case 0x8:
1812
                        if (xop & 0x10)
1813
                            gen_op_addx_T1_T0_cc();
1814
                        else
1815
                            gen_op_addx_T1_T0();
1816
                        break;
1817
#ifdef TARGET_SPARC64
1818
                    case 0x9: /* V9 mulx */
1819
                        gen_op_mulx_T1_T0();
1820
                        break;
1821
#endif
1822
                    case 0xa:
1823
                        gen_op_umul_T1_T0();
1824
                        if (xop & 0x10)
1825
                            gen_op_logic_T0_cc();
1826
                        break;
1827
                    case 0xb:
1828
                        gen_op_smul_T1_T0();
1829
                        if (xop & 0x10)
1830
                            gen_op_logic_T0_cc();
1831
                        break;
1832
                    case 0xc:
1833
                        if (xop & 0x10)
1834
                            gen_op_subx_T1_T0_cc();
1835
                        else
1836
                            gen_op_subx_T1_T0();
1837
                        break;
1838
#ifdef TARGET_SPARC64
1839
                    case 0xd: /* V9 udivx */
1840
                        gen_op_udivx_T1_T0();
1841
                        break;
1842
#endif
1843
                    case 0xe:
1844
                        gen_op_udiv_T1_T0();
1845
                        if (xop & 0x10)
1846
                            gen_op_div_cc();
1847
                        break;
1848
                    case 0xf:
1849
                        gen_op_sdiv_T1_T0();
1850
                        if (xop & 0x10)
1851
                            gen_op_div_cc();
1852
                        break;
1853
                    default:
1854
                        goto illegal_insn;
1855
                    }
1856
                    gen_movl_T0_reg(rd);
1857
                } else {
1858
                    switch (xop) {
1859
                    case 0x20: /* taddcc */
1860
                        gen_op_tadd_T1_T0_cc();
1861
                        gen_movl_T0_reg(rd);
1862
                        break;
1863
                    case 0x21: /* tsubcc */
1864
                        gen_op_tsub_T1_T0_cc();
1865
                        gen_movl_T0_reg(rd);
1866
                        break;
1867
                    case 0x22: /* taddcctv */
1868
                        gen_op_tadd_T1_T0_ccTV();
1869
                        gen_movl_T0_reg(rd);
1870
                        break;
1871
                    case 0x23: /* tsubcctv */
1872
                        gen_op_tsub_T1_T0_ccTV();
1873
                        gen_movl_T0_reg(rd);
1874
                        break;
1875
                    case 0x24: /* mulscc */
1876
                        gen_op_mulscc_T1_T0();
1877
                        gen_movl_T0_reg(rd);
1878
                        break;
1879
#ifndef TARGET_SPARC64
1880
                    case 0x25:        /* sll */
1881
                        gen_op_sll();
1882
                        gen_movl_T0_reg(rd);
1883
                        break;
1884
                    case 0x26:  /* srl */
1885
                        gen_op_srl();
1886
                        gen_movl_T0_reg(rd);
1887
                        break;
1888
                    case 0x27:  /* sra */
1889
                        gen_op_sra();
1890
                        gen_movl_T0_reg(rd);
1891
                        break;
1892
#endif
1893
                    case 0x30:
1894
                        {
1895
                            switch(rd) {
1896
                            case 0: /* wry */
1897
                                gen_op_xor_T1_T0();
1898
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1899
                                break;
1900
#ifndef TARGET_SPARC64
1901
                            case 0x01 ... 0x0f: /* undefined in the
1902
                                                   SPARCv8 manual, nop
1903
                                                   on the microSPARC
1904
                                                   II */
1905
                            case 0x10 ... 0x1f: /* implementation-dependent
1906
                                                   in the SPARCv8
1907
                                                   manual, nop on the
1908
                                                   microSPARC II */
1909
                                break;
1910
#else
1911
                            case 0x2: /* V9 wrccr */
1912
                                gen_op_wrccr();
1913
                                break;
1914
                            case 0x3: /* V9 wrasi */
1915
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
1916
                                break;
1917
                            case 0x6: /* V9 wrfprs */
1918
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
1919
                                break;
1920
                            case 0xf: /* V9 sir, nop if user */
1921
#if !defined(CONFIG_USER_ONLY)
1922
                                if (supervisor(dc))
1923
                                    gen_op_sir();
1924
#endif
1925
                                break;
1926
                            case 0x13: /* Graphics Status */
1927
                                if (gen_trap_ifnofpu(dc))
1928
                                    goto jmp_insn;
1929
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
1930
                                break;
1931
                            case 0x17: /* Tick compare */
1932
#if !defined(CONFIG_USER_ONLY)
1933
                                if (!supervisor(dc))
1934
                                    goto illegal_insn;
1935
#endif
1936
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
1937
                                break;
1938
                            case 0x18: /* System tick */
1939
#if !defined(CONFIG_USER_ONLY)
1940
                                if (!supervisor(dc))
1941
                                    goto illegal_insn;
1942
#endif
1943
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
1944
                                break;
1945
                            case 0x19: /* System tick compare */
1946
#if !defined(CONFIG_USER_ONLY)
1947
                                if (!supervisor(dc))
1948
                                    goto illegal_insn;
1949
#endif
1950
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
1951
                                break;
1952

    
1953
                            case 0x10: /* Performance Control */
1954
                            case 0x11: /* Performance Instrumentation Counter */
1955
                            case 0x12: /* Dispatch Control */
1956
                            case 0x14: /* Softint set */
1957
                            case 0x15: /* Softint clear */
1958
                            case 0x16: /* Softint write */
1959
#endif
1960
                            default:
1961
                                goto illegal_insn;
1962
                            }
1963
                        }
1964
                        break;
1965
#if !defined(CONFIG_USER_ONLY)
1966
                    case 0x31: /* wrpsr, V9 saved, restored */
1967
                        {
1968
                            if (!supervisor(dc))
1969
                                goto priv_insn;
1970
#ifdef TARGET_SPARC64
1971
                            switch (rd) {
1972
                            case 0:
1973
                                gen_op_saved();
1974
                                break;
1975
                            case 1:
1976
                                gen_op_restored();
1977
                                break;
1978
                            default:
1979
                                goto illegal_insn;
1980
                            }
1981
#else
1982
                            gen_op_xor_T1_T0();
1983
                            gen_op_wrpsr();
1984
                            save_state(dc);
1985
                            gen_op_next_insn();
1986
                            gen_op_movl_T0_0();
1987
                            gen_op_exit_tb();
1988
                            dc->is_br = 1;
1989
#endif
1990
                        }
1991
                        break;
1992
                    case 0x32: /* wrwim, V9 wrpr */
1993
                        {
1994
                            if (!supervisor(dc))
1995
                                goto priv_insn;
1996
                            gen_op_xor_T1_T0();
1997
#ifdef TARGET_SPARC64
1998
                            switch (rd) {
1999
                            case 0: // tpc
2000
                                gen_op_wrtpc();
2001
                                break;
2002
                            case 1: // tnpc
2003
                                gen_op_wrtnpc();
2004
                                break;
2005
                            case 2: // tstate
2006
                                gen_op_wrtstate();
2007
                                break;
2008
                            case 3: // tt
2009
                                gen_op_wrtt();
2010
                                break;
2011
                            case 4: // tick
2012
                                gen_op_wrtick();
2013
                                break;
2014
                            case 5: // tba
2015
                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
2016
                                break;
2017
                            case 6: // pstate
2018
                                gen_op_wrpstate();
2019
                                save_state(dc);
2020
                                gen_op_next_insn();
2021
                                gen_op_movl_T0_0();
2022
                                gen_op_exit_tb();
2023
                                dc->is_br = 1;
2024
                                break;
2025
                            case 7: // tl
2026
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
2027
                                break;
2028
                            case 8: // pil
2029
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
2030
                                break;
2031
                            case 9: // cwp
2032
                                gen_op_wrcwp();
2033
                                break;
2034
                            case 10: // cansave
2035
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
2036
                                break;
2037
                            case 11: // canrestore
2038
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
2039
                                break;
2040
                            case 12: // cleanwin
2041
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
2042
                                break;
2043
                            case 13: // otherwin
2044
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
2045
                                break;
2046
                            case 14: // wstate
2047
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
2048
                                break;
2049
                            default:
2050
                                goto illegal_insn;
2051
                            }
2052
#else
2053
                            gen_op_wrwim();
2054
#endif
2055
                        }
2056
                        break;
2057
#ifndef TARGET_SPARC64
2058
                    case 0x33: /* wrtbr, V9 unimp */
2059
                        {
2060
                            if (!supervisor(dc))
2061
                                goto priv_insn;
2062
                            gen_op_xor_T1_T0();
2063
                            gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
2064
                        }
2065
                        break;
2066
#endif
2067
#endif
2068
#ifdef TARGET_SPARC64
2069
                    case 0x2c: /* V9 movcc */
2070
                        {
2071
                            int cc = GET_FIELD_SP(insn, 11, 12);
2072
                            int cond = GET_FIELD_SP(insn, 14, 17);
2073
                            if (IS_IMM) {        /* immediate */
2074
                                rs2 = GET_FIELD_SPs(insn, 0, 10);
2075
                                gen_movl_simm_T1(rs2);
2076
                            }
2077
                            else {
2078
                                rs2 = GET_FIELD_SP(insn, 0, 4);
2079
                                gen_movl_reg_T1(rs2);
2080
                            }
2081
                            gen_movl_reg_T0(rd);
2082
                            flush_T2(dc);
2083
                            if (insn & (1 << 18)) {
2084
                                if (cc == 0)
2085
                                    gen_cond[0][cond]();
2086
                                else if (cc == 2)
2087
                                    gen_cond[1][cond]();
2088
                                else
2089
                                    goto illegal_insn;
2090
                            } else {
2091
                                gen_fcond[cc][cond]();
2092
                            }
2093
                            gen_op_mov_cc();
2094
                            gen_movl_T0_reg(rd);
2095
                            break;
2096
                        }
2097
                    case 0x2d: /* V9 sdivx */
2098
                        gen_op_sdivx_T1_T0();
2099
                        gen_movl_T0_reg(rd);
2100
                        break;
2101
                    case 0x2e: /* V9 popc */
2102
                        {
2103
                            if (IS_IMM) {        /* immediate */
2104
                                rs2 = GET_FIELD_SPs(insn, 0, 12);
2105
                                gen_movl_simm_T1(rs2);
2106
                                // XXX optimize: popc(constant)
2107
                            }
2108
                            else {
2109
                                rs2 = GET_FIELD_SP(insn, 0, 4);
2110
                                gen_movl_reg_T1(rs2);
2111
                            }
2112
                            gen_op_popc();
2113
                            gen_movl_T0_reg(rd);
2114
                        }
2115
                    case 0x2f: /* V9 movr */
2116
                        {
2117
                            int cond = GET_FIELD_SP(insn, 10, 12);
2118
                            rs1 = GET_FIELD(insn, 13, 17);
2119
                            flush_T2(dc);
2120
                            gen_movl_reg_T0(rs1);
2121
                            gen_cond_reg(cond);
2122
                            if (IS_IMM) {        /* immediate */
2123
                                rs2 = GET_FIELD_SPs(insn, 0, 10);
2124
                                gen_movl_simm_T1(rs2);
2125
                            }
2126
                            else {
2127
                                rs2 = GET_FIELD_SP(insn, 0, 4);
2128
                                gen_movl_reg_T1(rs2);
2129
                            }
2130
                            gen_movl_reg_T0(rd);
2131
                            gen_op_mov_cc();
2132
                            gen_movl_T0_reg(rd);
2133
                            break;
2134
                        }
2135
                    case 0x36: /* UltraSparc shutdown, VIS */
2136
                        {
2137
                            int opf = GET_FIELD_SP(insn, 5, 13);
2138
                            rs1 = GET_FIELD(insn, 13, 17);
2139
                            rs2 = GET_FIELD(insn, 27, 31);
2140

    
2141
                            switch (opf) {
2142
                            case 0x018: /* VIS I alignaddr */
2143
                                if (gen_trap_ifnofpu(dc))
2144
                                    goto jmp_insn;
2145
                                gen_movl_reg_T0(rs1);
2146
                                gen_movl_reg_T1(rs2);
2147
                                gen_op_alignaddr();
2148
                                gen_movl_T0_reg(rd);
2149
                                break;
2150
                            case 0x01a: /* VIS I alignaddrl */
2151
                                if (gen_trap_ifnofpu(dc))
2152
                                    goto jmp_insn;
2153
                                // XXX
2154
                                break;
2155
                            case 0x048: /* VIS I faligndata */
2156
                                if (gen_trap_ifnofpu(dc))
2157
                                    goto jmp_insn;
2158
                                gen_op_load_fpr_DT0(rs1);
2159
                                gen_op_load_fpr_DT1(rs2);
2160
                                gen_op_faligndata();
2161
                                gen_op_store_DT0_fpr(rd);
2162
                                break;
2163
                            default:
2164
                                goto illegal_insn;
2165
                            }
2166
                            break;
2167
                        }
2168
#endif
2169
                    default:
2170
                        goto illegal_insn;
2171
                    }
2172
                }
2173
            } else if (xop == 0x36 || xop == 0x37) { /* CPop1 & CPop2,
2174
                                                        V9 impdep1 &
2175
                                                        impdep2 */
2176
#ifdef TARGET_SPARC64
2177
                goto illegal_insn;
2178
#else
2179
                goto ncp_insn;
2180
#endif
2181
#ifdef TARGET_SPARC64
2182
            } else if (xop == 0x39) { /* V9 return */
2183
                rs1 = GET_FIELD(insn, 13, 17);
2184
                gen_movl_reg_T0(rs1);
2185
                if (IS_IMM) {        /* immediate */
2186
                    rs2 = GET_FIELDs(insn, 19, 31);
2187
#if defined(OPTIM)
2188
                    if (rs2) {
2189
#endif
2190
                        gen_movl_simm_T1(rs2);
2191
                        gen_op_add_T1_T0();
2192
#if defined(OPTIM)
2193
                    }
2194
#endif
2195
                } else {                /* register */
2196
                    rs2 = GET_FIELD(insn, 27, 31);
2197
#if defined(OPTIM)
2198
                    if (rs2) {
2199
#endif
2200
                        gen_movl_reg_T1(rs2);
2201
                        gen_op_add_T1_T0();
2202
#if defined(OPTIM)
2203
                    }
2204
#endif
2205
                }
2206
                gen_op_restore();
2207
                gen_mov_pc_npc(dc);
2208
                gen_op_movl_npc_T0();
2209
                dc->npc = DYNAMIC_PC;
2210
                goto jmp_insn;
2211
#endif
2212
            } else {
2213
                rs1 = GET_FIELD(insn, 13, 17);
2214
                gen_movl_reg_T0(rs1);
2215
                if (IS_IMM) {        /* immediate */
2216
                    rs2 = GET_FIELDs(insn, 19, 31);
2217
#if defined(OPTIM)
2218
                    if (rs2) {
2219
#endif
2220
                        gen_movl_simm_T1(rs2);
2221
                        gen_op_add_T1_T0();
2222
#if defined(OPTIM)
2223
                    }
2224
#endif
2225
                } else {                /* register */
2226
                    rs2 = GET_FIELD(insn, 27, 31);
2227
#if defined(OPTIM)
2228
                    if (rs2) {
2229
#endif
2230
                        gen_movl_reg_T1(rs2);
2231
                        gen_op_add_T1_T0();
2232
#if defined(OPTIM)
2233
                    }
2234
#endif
2235
                }
2236
                switch (xop) {
2237
                case 0x38:        /* jmpl */
2238
                    {
2239
                        if (rd != 0) {
2240
#ifdef TARGET_SPARC64
2241
                            if (dc->pc == (uint32_t)dc->pc) {
2242
                                gen_op_movl_T1_im(dc->pc);
2243
                            } else {
2244
                                gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
2245
                            }
2246
#else
2247
                            gen_op_movl_T1_im(dc->pc);
2248
#endif
2249
                            gen_movl_T1_reg(rd);
2250
                        }
2251
                        gen_mov_pc_npc(dc);
2252
                        gen_op_movl_npc_T0();
2253
                        dc->npc = DYNAMIC_PC;
2254
                    }
2255
                    goto jmp_insn;
2256
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2257
                case 0x39:        /* rett, V9 return */
2258
                    {
2259
                        if (!supervisor(dc))
2260
                            goto priv_insn;
2261
                        gen_mov_pc_npc(dc);
2262
                        gen_op_movl_npc_T0();
2263
                        dc->npc = DYNAMIC_PC;
2264
                        gen_op_rett();
2265
                    }
2266
                    goto jmp_insn;
2267
#endif
2268
                case 0x3b: /* flush */
2269
                    gen_op_flush_T0();
2270
                    break;
2271
                case 0x3c:        /* save */
2272
                    save_state(dc);
2273
                    gen_op_save();
2274
                    gen_movl_T0_reg(rd);
2275
                    break;
2276
                case 0x3d:        /* restore */
2277
                    save_state(dc);
2278
                    gen_op_restore();
2279
                    gen_movl_T0_reg(rd);
2280
                    break;
2281
#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
2282
                case 0x3e:      /* V9 done/retry */
2283
                    {
2284
                        switch (rd) {
2285
                        case 0:
2286
                            if (!supervisor(dc))
2287
                                goto priv_insn;
2288
                            dc->npc = DYNAMIC_PC;
2289
                            dc->pc = DYNAMIC_PC;
2290
                            gen_op_done();
2291
                            goto jmp_insn;
2292
                        case 1:
2293
                            if (!supervisor(dc))
2294
                                goto priv_insn;
2295
                            dc->npc = DYNAMIC_PC;
2296
                            dc->pc = DYNAMIC_PC;
2297
                            gen_op_retry();
2298
                            goto jmp_insn;
2299
                        default:
2300
                            goto illegal_insn;
2301
                        }
2302
                    }
2303
                    break;
2304
#endif
2305
                default:
2306
                    goto illegal_insn;
2307
                }
2308
            }
2309
            break;
2310
        }
2311
        break;
2312
    case 3:                        /* load/store instructions */
2313
        {
2314
            unsigned int xop = GET_FIELD(insn, 7, 12);
2315
            rs1 = GET_FIELD(insn, 13, 17);
2316
            gen_movl_reg_T0(rs1);
2317
            if (IS_IMM) {        /* immediate */
2318
                rs2 = GET_FIELDs(insn, 19, 31);
2319
#if defined(OPTIM)
2320
                if (rs2 != 0) {
2321
#endif
2322
                    gen_movl_simm_T1(rs2);
2323
                    gen_op_add_T1_T0();
2324
#if defined(OPTIM)
2325
                }
2326
#endif
2327
            } else {                /* register */
2328
                rs2 = GET_FIELD(insn, 27, 31);
2329
#if defined(OPTIM)
2330
                if (rs2 != 0) {
2331
#endif
2332
                    gen_movl_reg_T1(rs2);
2333
                    gen_op_add_T1_T0();
2334
#if defined(OPTIM)
2335
                }
2336
#endif
2337
            }
2338
            if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
2339
                    (xop > 0x17 && xop <= 0x1d ) || \
2340
                    (xop > 0x2c && xop <= 0x33) || xop == 0x1f) {
2341
                switch (xop) {
2342
                case 0x0:        /* load word */
2343
                    gen_op_ldst(ld);
2344
                    break;
2345
                case 0x1:        /* load unsigned byte */
2346
                    gen_op_ldst(ldub);
2347
                    break;
2348
                case 0x2:        /* load unsigned halfword */
2349
                    gen_op_ldst(lduh);
2350
                    break;
2351
                case 0x3:        /* load double word */
2352
                    if (rd & 1)
2353
                        goto illegal_insn;
2354
                    gen_op_ldst(ldd);
2355
                    gen_movl_T0_reg(rd + 1);
2356
                    break;
2357
                case 0x9:        /* load signed byte */
2358
                    gen_op_ldst(ldsb);
2359
                    break;
2360
                case 0xa:        /* load signed halfword */
2361
                    gen_op_ldst(ldsh);
2362
                    break;
2363
                case 0xd:        /* ldstub -- XXX: should be atomically */
2364
                    gen_op_ldst(ldstub);
2365
                    break;
2366
                case 0x0f:        /* swap register with memory. Also atomically */
2367
                    gen_movl_reg_T1(rd);
2368
                    gen_op_ldst(swap);
2369
                    break;
2370
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2371
                case 0x10:        /* load word alternate */
2372
#ifndef TARGET_SPARC64
2373
                    if (IS_IMM)
2374
                        goto illegal_insn;
2375
                    if (!supervisor(dc))
2376
                        goto priv_insn;
2377
#endif
2378
                    gen_op_lda(insn, 1, 4, 0);
2379
                    break;
2380
                case 0x11:        /* load unsigned byte alternate */
2381
#ifndef TARGET_SPARC64
2382
                    if (IS_IMM)
2383
                        goto illegal_insn;
2384
                    if (!supervisor(dc))
2385
                        goto priv_insn;
2386
#endif
2387
                    gen_op_lduba(insn, 1, 1, 0);
2388
                    break;
2389
                case 0x12:        /* load unsigned halfword alternate */
2390
#ifndef TARGET_SPARC64
2391
                    if (IS_IMM)
2392
                        goto illegal_insn;
2393
                    if (!supervisor(dc))
2394
                        goto priv_insn;
2395
#endif
2396
                    gen_op_lduha(insn, 1, 2, 0);
2397
                    break;
2398
                case 0x13:        /* load double word alternate */
2399
#ifndef TARGET_SPARC64
2400
                    if (IS_IMM)
2401
                        goto illegal_insn;
2402
                    if (!supervisor(dc))
2403
                        goto priv_insn;
2404
#endif
2405
                    if (rd & 1)
2406
                        goto illegal_insn;
2407
                    gen_op_ldda(insn, 1, 8, 0);
2408
                    gen_movl_T0_reg(rd + 1);
2409
                    break;
2410
                case 0x19:        /* load signed byte alternate */
2411
#ifndef TARGET_SPARC64
2412
                    if (IS_IMM)
2413
                        goto illegal_insn;
2414
                    if (!supervisor(dc))
2415
                        goto priv_insn;
2416
#endif
2417
                    gen_op_ldsba(insn, 1, 1, 1);
2418
                    break;
2419
                case 0x1a:        /* load signed halfword alternate */
2420
#ifndef TARGET_SPARC64
2421
                    if (IS_IMM)
2422
                        goto illegal_insn;
2423
                    if (!supervisor(dc))
2424
                        goto priv_insn;
2425
#endif
2426
                    gen_op_ldsha(insn, 1, 2 ,1);
2427
                    break;
2428
                case 0x1d:        /* ldstuba -- XXX: should be atomically */
2429
#ifndef TARGET_SPARC64
2430
                    if (IS_IMM)
2431
                        goto illegal_insn;
2432
                    if (!supervisor(dc))
2433
                        goto priv_insn;
2434
#endif
2435
                    gen_op_ldstuba(insn, 1, 1, 0);
2436
                    break;
2437
                case 0x1f:        /* swap reg with alt. memory. Also atomically */
2438
#ifndef TARGET_SPARC64
2439
                    if (IS_IMM)
2440
                        goto illegal_insn;
2441
                    if (!supervisor(dc))
2442
                        goto priv_insn;
2443
#endif
2444
                    gen_movl_reg_T1(rd);
2445
                    gen_op_swapa(insn, 1, 4, 0);
2446
                    break;
2447

    
2448
#ifndef TARGET_SPARC64
2449
                case 0x30: /* ldc */
2450
                case 0x31: /* ldcsr */
2451
                case 0x33: /* lddc */
2452
                    goto ncp_insn;
2453
                    /* avoid warnings */
2454
                    (void) &gen_op_stfa;
2455
                    (void) &gen_op_stdfa;
2456
                    (void) &gen_op_ldfa;
2457
                    (void) &gen_op_lddfa;
2458
#else
2459
#if !defined(CONFIG_USER_ONLY)
2460
                    (void) &gen_op_cas;
2461
                    (void) &gen_op_casx;
2462
#endif
2463
#endif
2464
#endif
2465
#ifdef TARGET_SPARC64
2466
                case 0x08: /* V9 ldsw */
2467
                    gen_op_ldst(ldsw);
2468
                    break;
2469
                case 0x0b: /* V9 ldx */
2470
                    gen_op_ldst(ldx);
2471
                    break;
2472
                case 0x18: /* V9 ldswa */
2473
                    gen_op_ldswa(insn, 1, 4, 1);
2474
                    break;
2475
                case 0x1b: /* V9 ldxa */
2476
                    gen_op_ldxa(insn, 1, 8, 0);
2477
                    break;
2478
                case 0x2d: /* V9 prefetch, no effect */
2479
                    goto skip_move;
2480
                case 0x30: /* V9 ldfa */
2481
                    gen_op_ldfa(insn, 1, 8, 0); // XXX
2482
                    break;
2483
                case 0x33: /* V9 lddfa */
2484
                    gen_op_lddfa(insn, 1, 8, 0); // XXX
2485

    
2486
                    break;
2487
                case 0x3d: /* V9 prefetcha, no effect */
2488
                    goto skip_move;
2489
                case 0x32: /* V9 ldqfa */
2490
                    goto nfpu_insn;
2491
#endif
2492
                default:
2493
                    goto illegal_insn;
2494
                }
2495
                gen_movl_T1_reg(rd);
2496
#ifdef TARGET_SPARC64
2497
            skip_move: ;
2498
#endif
2499
            } else if (xop >= 0x20 && xop < 0x24) {
2500
                if (gen_trap_ifnofpu(dc))
2501
                    goto jmp_insn;
2502
                switch (xop) {
2503
                case 0x20:        /* load fpreg */
2504
                    gen_op_ldst(ldf);
2505
                    gen_op_store_FT0_fpr(rd);
2506
                    break;
2507
                case 0x21:        /* load fsr */
2508
                    gen_op_ldst(ldf);
2509
                    gen_op_ldfsr();
2510
                    break;
2511
                case 0x22:      /* load quad fpreg */
2512
                    goto nfpu_insn;
2513
                case 0x23:        /* load double fpreg */
2514
                    gen_op_ldst(lddf);
2515
                    gen_op_store_DT0_fpr(DFPREG(rd));
2516
                    break;
2517
                default:
2518
                    goto illegal_insn;
2519
                }
2520
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
2521
                       xop == 0xe || xop == 0x1e) {
2522
                gen_movl_reg_T1(rd);
2523
                switch (xop) {
2524
                case 0x4:
2525
                    gen_op_ldst(st);
2526
                    break;
2527
                case 0x5:
2528
                    gen_op_ldst(stb);
2529
                    break;
2530
                case 0x6:
2531
                    gen_op_ldst(sth);
2532
                    break;
2533
                case 0x7:
2534
                    if (rd & 1)
2535
                        goto illegal_insn;
2536
                    flush_T2(dc);
2537
                    gen_movl_reg_T2(rd + 1);
2538
                    gen_op_ldst(std);
2539
                    break;
2540
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2541
                case 0x14:
2542
#ifndef TARGET_SPARC64
2543
                    if (IS_IMM)
2544
                        goto illegal_insn;
2545
                    if (!supervisor(dc))
2546
                        goto priv_insn;
2547
#endif
2548
                    gen_op_sta(insn, 0, 4, 0);
2549
                    break;
2550
                case 0x15:
2551
#ifndef TARGET_SPARC64
2552
                    if (IS_IMM)
2553
                        goto illegal_insn;
2554
                    if (!supervisor(dc))
2555
                        goto priv_insn;
2556
#endif
2557
                    gen_op_stba(insn, 0, 1, 0);
2558
                    break;
2559
                case 0x16:
2560
#ifndef TARGET_SPARC64
2561
                    if (IS_IMM)
2562
                        goto illegal_insn;
2563
                    if (!supervisor(dc))
2564
                        goto priv_insn;
2565
#endif
2566
                    gen_op_stha(insn, 0, 2, 0);
2567
                    break;
2568
                case 0x17:
2569
#ifndef TARGET_SPARC64
2570
                    if (IS_IMM)
2571
                        goto illegal_insn;
2572
                    if (!supervisor(dc))
2573
                        goto priv_insn;
2574
#endif
2575
                    if (rd & 1)
2576
                        goto illegal_insn;
2577
                    flush_T2(dc);
2578
                    gen_movl_reg_T2(rd + 1);
2579
                    gen_op_stda(insn, 0, 8, 0);
2580
                    break;
2581
#endif
2582
#ifdef TARGET_SPARC64
2583
                case 0x0e: /* V9 stx */
2584
                    gen_op_ldst(stx);
2585
                    break;
2586
                case 0x1e: /* V9 stxa */
2587
                    gen_op_stxa(insn, 0, 8, 0); // XXX
2588
                    break;
2589
#endif
2590
                default:
2591
                    goto illegal_insn;
2592
                }
2593
            } else if (xop > 0x23 && xop < 0x28) {
2594
                if (gen_trap_ifnofpu(dc))
2595
                    goto jmp_insn;
2596
                switch (xop) {
2597
                case 0x24:
2598
                    gen_op_load_fpr_FT0(rd);
2599
                    gen_op_ldst(stf);
2600
                    break;
2601
                case 0x25: /* stfsr, V9 stxfsr */
2602
                    gen_op_stfsr();
2603
                    gen_op_ldst(stf);
2604
                    break;
2605
#if !defined(CONFIG_USER_ONLY)
2606
                case 0x26: /* stdfq */
2607
                    if (!supervisor(dc))
2608
                        goto priv_insn;
2609
                    if (gen_trap_ifnofpu(dc))
2610
                        goto jmp_insn;
2611
                    goto nfq_insn;
2612
#endif
2613
                case 0x27:
2614
                    gen_op_load_fpr_DT0(DFPREG(rd));
2615
                    gen_op_ldst(stdf);
2616
                    break;
2617
                default:
2618
                    goto illegal_insn;
2619
                }
2620
            } else if (xop > 0x33 && xop < 0x3f) {
2621
                switch (xop) {
2622
#ifdef TARGET_SPARC64
2623
                case 0x34: /* V9 stfa */
2624
                    gen_op_stfa(insn, 0, 0, 0); // XXX
2625
                    break;
2626
                case 0x37: /* V9 stdfa */
2627
                    gen_op_stdfa(insn, 0, 0, 0); // XXX
2628
                    break;
2629
                case 0x3c: /* V9 casa */
2630
                    gen_op_casa(insn, 0, 4, 0); // XXX
2631
                    break;
2632
                case 0x3e: /* V9 casxa */
2633
                    gen_op_casxa(insn, 0, 8, 0); // XXX
2634
                    break;
2635
                case 0x36: /* V9 stqfa */
2636
                    goto nfpu_insn;
2637
#else
2638
                case 0x34: /* stc */
2639
                case 0x35: /* stcsr */
2640
                case 0x36: /* stdcq */
2641
                case 0x37: /* stdc */
2642
                    goto ncp_insn;
2643
#endif
2644
                default:
2645
                    goto illegal_insn;
2646
                }
2647
            }
2648
            else
2649
                goto illegal_insn;
2650
        }
2651
        break;
2652
    }
2653
    /* default case for non jump instructions */
2654
    if (dc->npc == DYNAMIC_PC) {
2655
        dc->pc = DYNAMIC_PC;
2656
        gen_op_next_insn();
2657
    } else if (dc->npc == JUMP_PC) {
2658
        /* we can do a static jump */
2659
        gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
2660
        dc->is_br = 1;
2661
    } else {
2662
        dc->pc = dc->npc;
2663
        dc->npc = dc->npc + 4;
2664
    }
2665
 jmp_insn:
2666
    return;
2667
 illegal_insn:
2668
    save_state(dc);
2669
    gen_op_exception(TT_ILL_INSN);
2670
    dc->is_br = 1;
2671
    return;
2672
#if !defined(CONFIG_USER_ONLY)
2673
 priv_insn:
2674
    save_state(dc);
2675
    gen_op_exception(TT_PRIV_INSN);
2676
    dc->is_br = 1;
2677
    return;
2678
#endif
2679
 nfpu_insn:
2680
    save_state(dc);
2681
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
2682
    dc->is_br = 1;
2683
    return;
2684
#if !defined(CONFIG_USER_ONLY)
2685
 nfq_insn:
2686
    save_state(dc);
2687
    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
2688
    dc->is_br = 1;
2689
    return;
2690
#endif
2691
#ifndef TARGET_SPARC64
2692
 ncp_insn:
2693
    save_state(dc);
2694
    gen_op_exception(TT_NCP_INSN);
2695
    dc->is_br = 1;
2696
    return;
2697
#endif
2698
}
2699

    
2700
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2701
                                                 int spc, CPUSPARCState *env)
2702
{
2703
    target_ulong pc_start, last_pc;
2704
    uint16_t *gen_opc_end;
2705
    DisasContext dc1, *dc = &dc1;
2706
    int j, lj = -1;
2707

    
2708
    memset(dc, 0, sizeof(DisasContext));
2709
    dc->tb = tb;
2710
    pc_start = tb->pc;
2711
    dc->pc = pc_start;
2712
    last_pc = dc->pc;
2713
    dc->npc = (target_ulong) tb->cs_base;
2714
#if defined(CONFIG_USER_ONLY)
2715
    dc->mem_idx = 0;
2716
    dc->fpu_enabled = 1;
2717
#else
2718
    dc->mem_idx = ((env->psrs) != 0);
2719
#ifdef TARGET_SPARC64
2720
    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
2721
#else
2722
    dc->fpu_enabled = ((env->psref) != 0);
2723
#endif
2724
#endif
2725
    gen_opc_ptr = gen_opc_buf;
2726
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2727
    gen_opparam_ptr = gen_opparam_buf;
2728
    nb_gen_labels = 0;
2729

    
2730
    do {
2731
        if (env->nb_breakpoints > 0) {
2732
            for(j = 0; j < env->nb_breakpoints; j++) {
2733
                if (env->breakpoints[j] == dc->pc) {
2734
                    if (dc->pc != pc_start)
2735
                        save_state(dc);
2736
                    gen_op_debug();
2737
                    gen_op_movl_T0_0();
2738
                    gen_op_exit_tb();
2739
                    dc->is_br = 1;
2740
                    goto exit_gen_loop;
2741
                }
2742
            }
2743
        }
2744
        if (spc) {
2745
            if (loglevel > 0)
2746
                fprintf(logfile, "Search PC...\n");
2747
            j = gen_opc_ptr - gen_opc_buf;
2748
            if (lj < j) {
2749
                lj++;
2750
                while (lj < j)
2751
                    gen_opc_instr_start[lj++] = 0;
2752
                gen_opc_pc[lj] = dc->pc;
2753
                gen_opc_npc[lj] = dc->npc;
2754
                gen_opc_instr_start[lj] = 1;
2755
            }
2756
        }
2757
        last_pc = dc->pc;
2758
        disas_sparc_insn(dc);
2759

    
2760
        if (dc->is_br)
2761
            break;
2762
        /* if the next PC is different, we abort now */
2763
        if (dc->pc != (last_pc + 4))
2764
            break;
2765
        /* if we reach a page boundary, we stop generation so that the
2766
           PC of a TT_TFAULT exception is always in the right page */
2767
        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
2768
            break;
2769
        /* if single step mode, we generate only one instruction and
2770
           generate an exception */
2771
        if (env->singlestep_enabled) {
2772
            gen_jmp_im(dc->pc);
2773
            gen_op_movl_T0_0();
2774
            gen_op_exit_tb();
2775
            break;
2776
        }
2777
    } while ((gen_opc_ptr < gen_opc_end) &&
2778
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2779

    
2780
 exit_gen_loop:
2781
    if (!dc->is_br) {
2782
        if (dc->pc != DYNAMIC_PC && 
2783
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2784
            /* static PC and NPC: we can use direct chaining */
2785
            gen_branch(dc, (long)tb, dc->pc, dc->npc);
2786
        } else {
2787
            if (dc->pc != DYNAMIC_PC)
2788
                gen_jmp_im(dc->pc);
2789
            save_npc(dc);
2790
            gen_op_movl_T0_0();
2791
            gen_op_exit_tb();
2792
        }
2793
    }
2794
    *gen_opc_ptr = INDEX_op_end;
2795
    if (spc) {
2796
        j = gen_opc_ptr - gen_opc_buf;
2797
        lj++;
2798
        while (lj <= j)
2799
            gen_opc_instr_start[lj++] = 0;
2800
        tb->size = 0;
2801
#if 0
2802
        if (loglevel > 0) {
2803
            page_dump(logfile);
2804
        }
2805
#endif
2806
        gen_opc_jump_pc[0] = dc->jump_pc[0];
2807
        gen_opc_jump_pc[1] = dc->jump_pc[1];
2808
    } else {
2809
        tb->size = last_pc + 4 - pc_start;
2810
    }
2811
#ifdef DEBUG_DISAS
2812
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2813
        fprintf(logfile, "--------------\n");
2814
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2815
        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2816
        fprintf(logfile, "\n");
2817
        if (loglevel & CPU_LOG_TB_OP) {
2818
            fprintf(logfile, "OP:\n");
2819
            dump_ops(gen_opc_buf, gen_opparam_buf);
2820
            fprintf(logfile, "\n");
2821
        }
2822
    }
2823
#endif
2824
    return 0;
2825
}
2826

    
2827
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2828
{
2829
    return gen_intermediate_code_internal(tb, 0, env);
2830
}
2831

    
2832
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2833
{
2834
    return gen_intermediate_code_internal(tb, 1, env);
2835
}
2836

    
2837
extern int ram_size;
2838

    
2839
void cpu_reset(CPUSPARCState *env)
2840
{
2841
    memset(env, 0, sizeof(*env));
2842
    tlb_flush(env, 1);
2843
    env->cwp = 0;
2844
    env->wim = 1;
2845
    env->regwptr = env->regbase + (env->cwp * 16);
2846
#if defined(CONFIG_USER_ONLY)
2847
    env->user_mode_only = 1;
2848
#ifdef TARGET_SPARC64
2849
    env->cleanwin = NWINDOWS - 1;
2850
    env->cansave = NWINDOWS - 1;
2851
#endif
2852
#else
2853
    env->psrs = 1;
2854
    env->psrps = 1;
2855
    env->gregs[1] = ram_size;
2856
#ifdef TARGET_SPARC64
2857
    env->pstate = PS_PRIV;
2858
    env->pc = 0x1fff0000000ULL;
2859
#else
2860
    env->pc = 0xffd00000;
2861
#endif
2862
    env->npc = env->pc + 4;
2863
#endif
2864
}
2865

    
2866
CPUSPARCState *cpu_sparc_init(void)
2867
{
2868
    CPUSPARCState *env;
2869

    
2870
    env = qemu_mallocz(sizeof(CPUSPARCState));
2871
    if (!env)
2872
        return NULL;
2873
    cpu_exec_init(env);
2874
    cpu_reset(env);
2875
    return (env);
2876
}
2877

    
2878
static const sparc_def_t sparc_defs[] = {
2879
#ifdef TARGET_SPARC64
2880
    {
2881
        .name = "TI UltraSparc II",
2882
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
2883
                       | (MAXTL << 8) | (NWINDOWS - 1)),
2884
        .fpu_version = 0x00000000,
2885
        .mmu_version = 0,
2886
    },
2887
#else
2888
    {
2889
        .name = "Fujitsu MB86904",
2890
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
2891
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
2892
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
2893
    },
2894
    {
2895
        /* XXX: Replace with real values */
2896
        .name = "TI SuperSparc II",
2897
        .iu_version = 0x40000000,
2898
        .fpu_version = 0x00000000,
2899
        .mmu_version = 0x00000000,
2900
    },
2901
#endif
2902
};
2903

    
2904
int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
2905
{
2906
    int ret;
2907
    unsigned int i;
2908

    
2909
    ret = -1;
2910
    *def = NULL;
2911
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2912
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
2913
            *def = &sparc_defs[i];
2914
            ret = 0;
2915
            break;
2916
        }
2917
    }
2918

    
2919
    return ret;
2920
}
2921

    
2922
void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2923
{
2924
    unsigned int i;
2925

    
2926
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2927
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
2928
                       sparc_defs[i].name,
2929
                       sparc_defs[i].iu_version,
2930
                       sparc_defs[i].fpu_version,
2931
                       sparc_defs[i].mmu_version);
2932
    }
2933
}
2934

    
2935
int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
2936
{
2937
    env->version = def->iu_version;
2938
    env->fsr = def->fpu_version;
2939
#if !defined(TARGET_SPARC64)
2940
    env->mmuregs[0] = def->mmu_version;
2941
#endif
2942
    return 0;
2943
}
2944

    
2945
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
2946

    
2947
void cpu_dump_state(CPUState *env, FILE *f, 
2948
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2949
                    int flags)
2950
{
2951
    int i, x;
2952

    
2953
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
2954
    cpu_fprintf(f, "General Registers:\n");
2955
    for (i = 0; i < 4; i++)
2956
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2957
    cpu_fprintf(f, "\n");
2958
    for (; i < 8; i++)
2959
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2960
    cpu_fprintf(f, "\nCurrent Register Window:\n");
2961
    for (x = 0; x < 3; x++) {
2962
        for (i = 0; i < 4; i++)
2963
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2964
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
2965
                    env->regwptr[i + x * 8]);
2966
        cpu_fprintf(f, "\n");
2967
        for (; i < 8; i++)
2968
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2969
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
2970
                    env->regwptr[i + x * 8]);
2971
        cpu_fprintf(f, "\n");
2972
    }
2973
    cpu_fprintf(f, "\nFloating Point Registers:\n");
2974
    for (i = 0; i < 32; i++) {
2975
        if ((i & 3) == 0)
2976
            cpu_fprintf(f, "%%f%02d:", i);
2977
        cpu_fprintf(f, " %016lf", env->fpr[i]);
2978
        if ((i & 3) == 3)
2979
            cpu_fprintf(f, "\n");
2980
    }
2981
#ifdef TARGET_SPARC64
2982
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
2983
                env->pstate, GET_CCR(env), env->asi, env->tl);
2984
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
2985
                env->cansave, env->canrestore, env->otherwin, env->wstate,
2986
                env->cleanwin, NWINDOWS - 1 - env->cwp);
2987
#else
2988
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
2989
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
2990
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
2991
            env->psrs?'S':'-', env->psrps?'P':'-', 
2992
            env->psret?'E':'-', env->wim);
2993
#endif
2994
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
2995
}
2996

    
2997
#if defined(CONFIG_USER_ONLY)
2998
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2999
{
3000
    return addr;
3001
}
3002

    
3003
#else
3004
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
3005
                                 int *access_index, target_ulong address, int rw,
3006
                                 int is_user);
3007

    
3008
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
3009
{
3010
    target_phys_addr_t phys_addr;
3011
    int prot, access_index;
3012

    
3013
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
3014
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
3015
            return -1;
3016
    return phys_addr;
3017
}
3018
#endif
3019

    
3020
void helper_flush(target_ulong addr)
3021
{
3022
    addr &= ~7;
3023
    tb_invalidate_page_range(addr, addr + 8);
3024
}