Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ fcc72045

History | View | Annotate | Download (78.8 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
#endif
1016
            case 0x2:                /* BN+x */
1017
                {
1018
                    target = GET_FIELD(insn, 10, 31);
1019
                    target = sign_extend(target, 22);
1020
                    target <<= 2;
1021
                    do_branch(dc, target, insn, 0);
1022
                    goto jmp_insn;
1023
                }
1024
            case 0x6:                /* FBN+x */
1025
                {
1026
                    if (gen_trap_ifnofpu(dc))
1027
                        goto jmp_insn;
1028
                    target = GET_FIELD(insn, 10, 31);
1029
                    target = sign_extend(target, 22);
1030
                    target <<= 2;
1031
                    do_fbranch(dc, target, insn, 0);
1032
                    goto jmp_insn;
1033
                }
1034
            case 0x4:                /* SETHI */
1035
#define OPTIM
1036
#if defined(OPTIM)
1037
                if (rd) { // nop
1038
#endif
1039
                    uint32_t value = GET_FIELD(insn, 10, 31);
1040
                    gen_movl_imm_T0(value << 10);
1041
                    gen_movl_T0_reg(rd);
1042
#if defined(OPTIM)
1043
                }
1044
#endif
1045
                break;
1046
            case 0x0:                /* UNIMPL */
1047
            default:
1048
                goto illegal_insn;
1049
            }
1050
            break;
1051
        }
1052
        break;
1053
    case 1:
1054
        /*CALL*/ {
1055
            target_long target = GET_FIELDs(insn, 2, 31) << 2;
1056

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

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

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

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

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

    
2420
#ifndef TARGET_SPARC64
2421
                case 0x30: /* ldc */
2422
                case 0x31: /* ldcsr */
2423
                case 0x33: /* lddc */
2424
                case 0x34: /* stc */
2425
                case 0x35: /* stcsr */
2426
                case 0x36: /* stdcq */
2427
                case 0x37: /* stdc */
2428
                    goto ncp_insn;
2429
                    break;
2430
                    /* avoid warnings */
2431
                    (void) &gen_op_stfa;
2432
                    (void) &gen_op_stdfa;
2433
                    (void) &gen_op_ldfa;
2434
                    (void) &gen_op_lddfa;
2435
#else
2436
#if !defined(CONFIG_USER_ONLY)
2437
                    (void) &gen_op_cas;
2438
                    (void) &gen_op_casx;
2439
#endif
2440
#endif
2441
#endif
2442
#ifdef TARGET_SPARC64
2443
                case 0x08: /* V9 ldsw */
2444
                    gen_op_ldst(ldsw);
2445
                    break;
2446
                case 0x0b: /* V9 ldx */
2447
                    gen_op_ldst(ldx);
2448
                    break;
2449
                case 0x18: /* V9 ldswa */
2450
                    gen_op_ldswa(insn, 1, 4, 1);
2451
                    break;
2452
                case 0x1b: /* V9 ldxa */
2453
                    gen_op_ldxa(insn, 1, 8, 0);
2454
                    break;
2455
                case 0x2d: /* V9 prefetch, no effect */
2456
                    goto skip_move;
2457
                case 0x30: /* V9 ldfa */
2458
                    gen_op_ldfa(insn, 1, 8, 0); // XXX
2459
                    break;
2460
                case 0x33: /* V9 lddfa */
2461
                    gen_op_lddfa(insn, 1, 8, 0); // XXX
2462

    
2463
                    break;
2464
                case 0x3d: /* V9 prefetcha, no effect */
2465
                    goto skip_move;
2466
                case 0x32: /* V9 ldqfa */
2467
                    goto nfpu_insn;
2468
#endif
2469
                default:
2470
                    goto illegal_insn;
2471
                }
2472
                gen_movl_T1_reg(rd);
2473
#ifdef TARGET_SPARC64
2474
            skip_move: ;
2475
#endif
2476
            } else if (xop >= 0x20 && xop < 0x24) {
2477
                if (gen_trap_ifnofpu(dc))
2478
                    goto jmp_insn;
2479
                switch (xop) {
2480
                case 0x20:        /* load fpreg */
2481
                    gen_op_ldst(ldf);
2482
                    gen_op_store_FT0_fpr(rd);
2483
                    break;
2484
                case 0x21:        /* load fsr */
2485
                    gen_op_ldst(ldf);
2486
                    gen_op_ldfsr();
2487
                    break;
2488
                case 0x22:      /* load quad fpreg */
2489
                    goto nfpu_insn;
2490
                case 0x23:        /* load double fpreg */
2491
                    gen_op_ldst(lddf);
2492
                    gen_op_store_DT0_fpr(DFPREG(rd));
2493
                    break;
2494
                default:
2495
                    goto illegal_insn;
2496
                }
2497
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
2498
                       xop == 0xe || xop == 0x1e) {
2499
                gen_movl_reg_T1(rd);
2500
                switch (xop) {
2501
                case 0x4:
2502
                    gen_op_ldst(st);
2503
                    break;
2504
                case 0x5:
2505
                    gen_op_ldst(stb);
2506
                    break;
2507
                case 0x6:
2508
                    gen_op_ldst(sth);
2509
                    break;
2510
                case 0x7:
2511
                    flush_T2(dc);
2512
                    gen_movl_reg_T2(rd + 1);
2513
                    gen_op_ldst(std);
2514
                    break;
2515
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2516
                case 0x14:
2517
#ifndef TARGET_SPARC64
2518
                    if (!supervisor(dc))
2519
                        goto priv_insn;
2520
#endif
2521
                    gen_op_sta(insn, 0, 4, 0);
2522
                    break;
2523
                case 0x15:
2524
#ifndef TARGET_SPARC64
2525
                    if (!supervisor(dc))
2526
                        goto priv_insn;
2527
#endif
2528
                    gen_op_stba(insn, 0, 1, 0);
2529
                    break;
2530
                case 0x16:
2531
#ifndef TARGET_SPARC64
2532
                    if (!supervisor(dc))
2533
                        goto priv_insn;
2534
#endif
2535
                    gen_op_stha(insn, 0, 2, 0);
2536
                    break;
2537
                case 0x17:
2538
#ifndef TARGET_SPARC64
2539
                    if (!supervisor(dc))
2540
                        goto priv_insn;
2541
#endif
2542
                    flush_T2(dc);
2543
                    gen_movl_reg_T2(rd + 1);
2544
                    gen_op_stda(insn, 0, 8, 0);
2545
                    break;
2546
#endif
2547
#ifdef TARGET_SPARC64
2548
                case 0x0e: /* V9 stx */
2549
                    gen_op_ldst(stx);
2550
                    break;
2551
                case 0x1e: /* V9 stxa */
2552
                    gen_op_stxa(insn, 0, 8, 0); // XXX
2553
                    break;
2554
#endif
2555
                default:
2556
                    goto illegal_insn;
2557
                }
2558
            } else if (xop > 0x23 && xop < 0x28) {
2559
                if (gen_trap_ifnofpu(dc))
2560
                    goto jmp_insn;
2561
                switch (xop) {
2562
                case 0x24:
2563
                    gen_op_load_fpr_FT0(rd);
2564
                    gen_op_ldst(stf);
2565
                    break;
2566
                case 0x25: /* stfsr, V9 stxfsr */
2567
                    gen_op_stfsr();
2568
                    gen_op_ldst(stf);
2569
                    break;
2570
                case 0x26: /* stdfq */
2571
                    goto nfpu_insn;
2572
                case 0x27:
2573
                    gen_op_load_fpr_DT0(DFPREG(rd));
2574
                    gen_op_ldst(stdf);
2575
                    break;
2576
                default:
2577
                    goto illegal_insn;
2578
                }
2579
            } else if (xop > 0x33 && xop < 0x3f) {
2580
#ifdef TARGET_SPARC64
2581
                switch (xop) {
2582
                case 0x34: /* V9 stfa */
2583
                    gen_op_stfa(insn, 0, 0, 0); // XXX
2584
                    break;
2585
                case 0x37: /* V9 stdfa */
2586
                    gen_op_stdfa(insn, 0, 0, 0); // XXX
2587
                    break;
2588
                case 0x3c: /* V9 casa */
2589
                    gen_op_casa(insn, 0, 4, 0); // XXX
2590
                    break;
2591
                case 0x3e: /* V9 casxa */
2592
                    gen_op_casxa(insn, 0, 8, 0); // XXX
2593
                    break;
2594
                case 0x36: /* V9 stqfa */
2595
                    goto nfpu_insn;
2596
                default:
2597
                    goto illegal_insn;
2598
                }
2599
#else
2600
                goto illegal_insn;
2601
#endif
2602
            }
2603
            else
2604
                goto illegal_insn;
2605
        }
2606
        break;
2607
    }
2608
    /* default case for non jump instructions */
2609
    if (dc->npc == DYNAMIC_PC) {
2610
        dc->pc = DYNAMIC_PC;
2611
        gen_op_next_insn();
2612
    } else if (dc->npc == JUMP_PC) {
2613
        /* we can do a static jump */
2614
        gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
2615
        dc->is_br = 1;
2616
    } else {
2617
        dc->pc = dc->npc;
2618
        dc->npc = dc->npc + 4;
2619
    }
2620
 jmp_insn:
2621
    return;
2622
 illegal_insn:
2623
    save_state(dc);
2624
    gen_op_exception(TT_ILL_INSN);
2625
    dc->is_br = 1;
2626
    return;
2627
#if !defined(CONFIG_USER_ONLY)
2628
 priv_insn:
2629
    save_state(dc);
2630
    gen_op_exception(TT_PRIV_INSN);
2631
    dc->is_br = 1;
2632
    return;
2633
#endif
2634
 nfpu_insn:
2635
    save_state(dc);
2636
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
2637
    dc->is_br = 1;
2638
    return;
2639
#ifndef TARGET_SPARC64
2640
 ncp_insn:
2641
    save_state(dc);
2642
    gen_op_exception(TT_NCP_INSN);
2643
    dc->is_br = 1;
2644
    return;
2645
#endif
2646
}
2647

    
2648
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2649
                                                 int spc, CPUSPARCState *env)
2650
{
2651
    target_ulong pc_start, last_pc;
2652
    uint16_t *gen_opc_end;
2653
    DisasContext dc1, *dc = &dc1;
2654
    int j, lj = -1;
2655

    
2656
    memset(dc, 0, sizeof(DisasContext));
2657
    dc->tb = tb;
2658
    pc_start = tb->pc;
2659
    dc->pc = pc_start;
2660
    last_pc = dc->pc;
2661
    dc->npc = (target_ulong) tb->cs_base;
2662
#if defined(CONFIG_USER_ONLY)
2663
    dc->mem_idx = 0;
2664
    dc->fpu_enabled = 1;
2665
#else
2666
    dc->mem_idx = ((env->psrs) != 0);
2667
#ifdef TARGET_SPARC64
2668
    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
2669
#else
2670
    dc->fpu_enabled = ((env->psref) != 0);
2671
#endif
2672
#endif
2673
    gen_opc_ptr = gen_opc_buf;
2674
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2675
    gen_opparam_ptr = gen_opparam_buf;
2676
    nb_gen_labels = 0;
2677

    
2678
    do {
2679
        if (env->nb_breakpoints > 0) {
2680
            for(j = 0; j < env->nb_breakpoints; j++) {
2681
                if (env->breakpoints[j] == dc->pc) {
2682
                    if (dc->pc != pc_start)
2683
                        save_state(dc);
2684
                    gen_op_debug();
2685
                    gen_op_movl_T0_0();
2686
                    gen_op_exit_tb();
2687
                    dc->is_br = 1;
2688
                    goto exit_gen_loop;
2689
                }
2690
            }
2691
        }
2692
        if (spc) {
2693
            if (loglevel > 0)
2694
                fprintf(logfile, "Search PC...\n");
2695
            j = gen_opc_ptr - gen_opc_buf;
2696
            if (lj < j) {
2697
                lj++;
2698
                while (lj < j)
2699
                    gen_opc_instr_start[lj++] = 0;
2700
                gen_opc_pc[lj] = dc->pc;
2701
                gen_opc_npc[lj] = dc->npc;
2702
                gen_opc_instr_start[lj] = 1;
2703
            }
2704
        }
2705
        last_pc = dc->pc;
2706
        disas_sparc_insn(dc);
2707

    
2708
        if (dc->is_br)
2709
            break;
2710
        /* if the next PC is different, we abort now */
2711
        if (dc->pc != (last_pc + 4))
2712
            break;
2713
        /* if we reach a page boundary, we stop generation so that the
2714
           PC of a TT_TFAULT exception is always in the right page */
2715
        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
2716
            break;
2717
        /* if single step mode, we generate only one instruction and
2718
           generate an exception */
2719
        if (env->singlestep_enabled) {
2720
            gen_jmp_im(dc->pc);
2721
            gen_op_movl_T0_0();
2722
            gen_op_exit_tb();
2723
            break;
2724
        }
2725
    } while ((gen_opc_ptr < gen_opc_end) &&
2726
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2727

    
2728
 exit_gen_loop:
2729
    if (!dc->is_br) {
2730
        if (dc->pc != DYNAMIC_PC && 
2731
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2732
            /* static PC and NPC: we can use direct chaining */
2733
            gen_branch(dc, (long)tb, dc->pc, dc->npc);
2734
        } else {
2735
            if (dc->pc != DYNAMIC_PC)
2736
                gen_jmp_im(dc->pc);
2737
            save_npc(dc);
2738
            gen_op_movl_T0_0();
2739
            gen_op_exit_tb();
2740
        }
2741
    }
2742
    *gen_opc_ptr = INDEX_op_end;
2743
    if (spc) {
2744
        j = gen_opc_ptr - gen_opc_buf;
2745
        lj++;
2746
        while (lj <= j)
2747
            gen_opc_instr_start[lj++] = 0;
2748
        tb->size = 0;
2749
#if 0
2750
        if (loglevel > 0) {
2751
            page_dump(logfile);
2752
        }
2753
#endif
2754
        gen_opc_jump_pc[0] = dc->jump_pc[0];
2755
        gen_opc_jump_pc[1] = dc->jump_pc[1];
2756
    } else {
2757
        tb->size = last_pc + 4 - pc_start;
2758
    }
2759
#ifdef DEBUG_DISAS
2760
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2761
        fprintf(logfile, "--------------\n");
2762
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2763
        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2764
        fprintf(logfile, "\n");
2765
        if (loglevel & CPU_LOG_TB_OP) {
2766
            fprintf(logfile, "OP:\n");
2767
            dump_ops(gen_opc_buf, gen_opparam_buf);
2768
            fprintf(logfile, "\n");
2769
        }
2770
    }
2771
#endif
2772
    return 0;
2773
}
2774

    
2775
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2776
{
2777
    return gen_intermediate_code_internal(tb, 0, env);
2778
}
2779

    
2780
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2781
{
2782
    return gen_intermediate_code_internal(tb, 1, env);
2783
}
2784

    
2785
extern int ram_size;
2786

    
2787
void cpu_reset(CPUSPARCState *env)
2788
{
2789
    memset(env, 0, sizeof(*env));
2790
    tlb_flush(env, 1);
2791
    env->cwp = 0;
2792
    env->wim = 1;
2793
    env->regwptr = env->regbase + (env->cwp * 16);
2794
#if defined(CONFIG_USER_ONLY)
2795
    env->user_mode_only = 1;
2796
#ifdef TARGET_SPARC64
2797
    env->cleanwin = NWINDOWS - 1;
2798
    env->cansave = NWINDOWS - 1;
2799
#endif
2800
#else
2801
    env->psrs = 1;
2802
    env->psrps = 1;
2803
    env->gregs[1] = ram_size;
2804
#ifdef TARGET_SPARC64
2805
    env->pstate = PS_PRIV;
2806
    env->pc = 0x1fff0000000ULL;
2807
#else
2808
    env->pc = 0xffd00000;
2809
#endif
2810
    env->npc = env->pc + 4;
2811
#endif
2812
}
2813

    
2814
CPUSPARCState *cpu_sparc_init(void)
2815
{
2816
    CPUSPARCState *env;
2817

    
2818
    env = qemu_mallocz(sizeof(CPUSPARCState));
2819
    if (!env)
2820
        return NULL;
2821
    cpu_exec_init(env);
2822
    cpu_reset(env);
2823
    return (env);
2824
}
2825

    
2826
static const sparc_def_t sparc_defs[] = {
2827
#ifdef TARGET_SPARC64
2828
    {
2829
        .name = "TI UltraSparc II",
2830
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
2831
                       | (MAXTL << 8) | (NWINDOWS - 1)),
2832
        .fpu_version = 0x00000000,
2833
        .mmu_version = 0,
2834
    },
2835
#else
2836
    {
2837
        .name = "Fujitsu MB86904",
2838
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
2839
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
2840
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
2841
    },
2842
#endif
2843
};
2844

    
2845
int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
2846
{
2847
    int ret;
2848
    unsigned int i;
2849

    
2850
    ret = -1;
2851
    *def = NULL;
2852
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2853
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
2854
            *def = &sparc_defs[i];
2855
            ret = 0;
2856
            break;
2857
        }
2858
    }
2859

    
2860
    return ret;
2861
}
2862

    
2863
void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2864
{
2865
    unsigned int i;
2866

    
2867
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2868
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
2869
                       sparc_defs[i].name,
2870
                       sparc_defs[i].iu_version,
2871
                       sparc_defs[i].fpu_version,
2872
                       sparc_defs[i].mmu_version);
2873
    }
2874
}
2875

    
2876
int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
2877
{
2878
    env->version = def->iu_version;
2879
    env->fsr = def->fpu_version;
2880
#if !defined(TARGET_SPARC64)
2881
    env->mmuregs[0] = def->mmu_version;
2882
#endif
2883
    return 0;
2884
}
2885

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

    
2888
void cpu_dump_state(CPUState *env, FILE *f, 
2889
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2890
                    int flags)
2891
{
2892
    int i, x;
2893

    
2894
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
2895
    cpu_fprintf(f, "General Registers:\n");
2896
    for (i = 0; i < 4; i++)
2897
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2898
    cpu_fprintf(f, "\n");
2899
    for (; i < 8; i++)
2900
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2901
    cpu_fprintf(f, "\nCurrent Register Window:\n");
2902
    for (x = 0; x < 3; x++) {
2903
        for (i = 0; i < 4; i++)
2904
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2905
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
2906
                    env->regwptr[i + x * 8]);
2907
        cpu_fprintf(f, "\n");
2908
        for (; i < 8; i++)
2909
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2910
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
2911
                    env->regwptr[i + x * 8]);
2912
        cpu_fprintf(f, "\n");
2913
    }
2914
    cpu_fprintf(f, "\nFloating Point Registers:\n");
2915
    for (i = 0; i < 32; i++) {
2916
        if ((i & 3) == 0)
2917
            cpu_fprintf(f, "%%f%02d:", i);
2918
        cpu_fprintf(f, " %016lf", env->fpr[i]);
2919
        if ((i & 3) == 3)
2920
            cpu_fprintf(f, "\n");
2921
    }
2922
#ifdef TARGET_SPARC64
2923
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
2924
                env->pstate, GET_CCR(env), env->asi, env->tl);
2925
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
2926
                env->cansave, env->canrestore, env->otherwin, env->wstate,
2927
                env->cleanwin, NWINDOWS - 1 - env->cwp);
2928
#else
2929
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
2930
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
2931
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
2932
            env->psrs?'S':'-', env->psrps?'P':'-', 
2933
            env->psret?'E':'-', env->wim);
2934
#endif
2935
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
2936
}
2937

    
2938
#if defined(CONFIG_USER_ONLY)
2939
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2940
{
2941
    return addr;
2942
}
2943

    
2944
#else
2945
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
2946
                                 int *access_index, target_ulong address, int rw,
2947
                                 int is_user);
2948

    
2949
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2950
{
2951
    target_phys_addr_t phys_addr;
2952
    int prot, access_index;
2953

    
2954
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
2955
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
2956
            return -1;
2957
    return phys_addr;
2958
}
2959
#endif
2960

    
2961
void helper_flush(target_ulong addr)
2962
{
2963
    addr &= ~7;
2964
    tb_invalidate_page_range(addr, addr + 8);
2965
}