Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ 4f14e88c

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

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

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

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

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

    
2683
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2684
                                                 int spc, CPUSPARCState *env)
2685
{
2686
    target_ulong pc_start, last_pc;
2687
    uint16_t *gen_opc_end;
2688
    DisasContext dc1, *dc = &dc1;
2689
    int j, lj = -1;
2690

    
2691
    memset(dc, 0, sizeof(DisasContext));
2692
    dc->tb = tb;
2693
    pc_start = tb->pc;
2694
    dc->pc = pc_start;
2695
    last_pc = dc->pc;
2696
    dc->npc = (target_ulong) tb->cs_base;
2697
#if defined(CONFIG_USER_ONLY)
2698
    dc->mem_idx = 0;
2699
    dc->fpu_enabled = 1;
2700
#else
2701
    dc->mem_idx = ((env->psrs) != 0);
2702
#ifdef TARGET_SPARC64
2703
    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
2704
#else
2705
    dc->fpu_enabled = ((env->psref) != 0);
2706
#endif
2707
#endif
2708
    gen_opc_ptr = gen_opc_buf;
2709
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2710
    gen_opparam_ptr = gen_opparam_buf;
2711
    nb_gen_labels = 0;
2712

    
2713
    do {
2714
        if (env->nb_breakpoints > 0) {
2715
            for(j = 0; j < env->nb_breakpoints; j++) {
2716
                if (env->breakpoints[j] == dc->pc) {
2717
                    if (dc->pc != pc_start)
2718
                        save_state(dc);
2719
                    gen_op_debug();
2720
                    gen_op_movl_T0_0();
2721
                    gen_op_exit_tb();
2722
                    dc->is_br = 1;
2723
                    goto exit_gen_loop;
2724
                }
2725
            }
2726
        }
2727
        if (spc) {
2728
            if (loglevel > 0)
2729
                fprintf(logfile, "Search PC...\n");
2730
            j = gen_opc_ptr - gen_opc_buf;
2731
            if (lj < j) {
2732
                lj++;
2733
                while (lj < j)
2734
                    gen_opc_instr_start[lj++] = 0;
2735
                gen_opc_pc[lj] = dc->pc;
2736
                gen_opc_npc[lj] = dc->npc;
2737
                gen_opc_instr_start[lj] = 1;
2738
            }
2739
        }
2740
        last_pc = dc->pc;
2741
        disas_sparc_insn(dc);
2742

    
2743
        if (dc->is_br)
2744
            break;
2745
        /* if the next PC is different, we abort now */
2746
        if (dc->pc != (last_pc + 4))
2747
            break;
2748
        /* if we reach a page boundary, we stop generation so that the
2749
           PC of a TT_TFAULT exception is always in the right page */
2750
        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
2751
            break;
2752
        /* if single step mode, we generate only one instruction and
2753
           generate an exception */
2754
        if (env->singlestep_enabled) {
2755
            gen_jmp_im(dc->pc);
2756
            gen_op_movl_T0_0();
2757
            gen_op_exit_tb();
2758
            break;
2759
        }
2760
    } while ((gen_opc_ptr < gen_opc_end) &&
2761
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2762

    
2763
 exit_gen_loop:
2764
    if (!dc->is_br) {
2765
        if (dc->pc != DYNAMIC_PC && 
2766
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2767
            /* static PC and NPC: we can use direct chaining */
2768
            gen_branch(dc, (long)tb, dc->pc, dc->npc);
2769
        } else {
2770
            if (dc->pc != DYNAMIC_PC)
2771
                gen_jmp_im(dc->pc);
2772
            save_npc(dc);
2773
            gen_op_movl_T0_0();
2774
            gen_op_exit_tb();
2775
        }
2776
    }
2777
    *gen_opc_ptr = INDEX_op_end;
2778
    if (spc) {
2779
        j = gen_opc_ptr - gen_opc_buf;
2780
        lj++;
2781
        while (lj <= j)
2782
            gen_opc_instr_start[lj++] = 0;
2783
        tb->size = 0;
2784
#if 0
2785
        if (loglevel > 0) {
2786
            page_dump(logfile);
2787
        }
2788
#endif
2789
        gen_opc_jump_pc[0] = dc->jump_pc[0];
2790
        gen_opc_jump_pc[1] = dc->jump_pc[1];
2791
    } else {
2792
        tb->size = last_pc + 4 - pc_start;
2793
    }
2794
#ifdef DEBUG_DISAS
2795
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2796
        fprintf(logfile, "--------------\n");
2797
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2798
        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2799
        fprintf(logfile, "\n");
2800
        if (loglevel & CPU_LOG_TB_OP) {
2801
            fprintf(logfile, "OP:\n");
2802
            dump_ops(gen_opc_buf, gen_opparam_buf);
2803
            fprintf(logfile, "\n");
2804
        }
2805
    }
2806
#endif
2807
    return 0;
2808
}
2809

    
2810
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2811
{
2812
    return gen_intermediate_code_internal(tb, 0, env);
2813
}
2814

    
2815
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2816
{
2817
    return gen_intermediate_code_internal(tb, 1, env);
2818
}
2819

    
2820
extern int ram_size;
2821

    
2822
void cpu_reset(CPUSPARCState *env)
2823
{
2824
    memset(env, 0, sizeof(*env));
2825
    tlb_flush(env, 1);
2826
    env->cwp = 0;
2827
    env->wim = 1;
2828
    env->regwptr = env->regbase + (env->cwp * 16);
2829
#if defined(CONFIG_USER_ONLY)
2830
    env->user_mode_only = 1;
2831
#ifdef TARGET_SPARC64
2832
    env->cleanwin = NWINDOWS - 1;
2833
    env->cansave = NWINDOWS - 1;
2834
#endif
2835
#else
2836
    env->psrs = 1;
2837
    env->psrps = 1;
2838
    env->gregs[1] = ram_size;
2839
#ifdef TARGET_SPARC64
2840
    env->pstate = PS_PRIV;
2841
    env->pc = 0x1fff0000000ULL;
2842
#else
2843
    env->pc = 0xffd00000;
2844
#endif
2845
    env->npc = env->pc + 4;
2846
#endif
2847
}
2848

    
2849
CPUSPARCState *cpu_sparc_init(void)
2850
{
2851
    CPUSPARCState *env;
2852

    
2853
    env = qemu_mallocz(sizeof(CPUSPARCState));
2854
    if (!env)
2855
        return NULL;
2856
    cpu_exec_init(env);
2857
    cpu_reset(env);
2858
    return (env);
2859
}
2860

    
2861
static const sparc_def_t sparc_defs[] = {
2862
#ifdef TARGET_SPARC64
2863
    {
2864
        .name = "TI UltraSparc II",
2865
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
2866
                       | (MAXTL << 8) | (NWINDOWS - 1)),
2867
        .fpu_version = 0x00000000,
2868
        .mmu_version = 0,
2869
    },
2870
#else
2871
    {
2872
        .name = "Fujitsu MB86904",
2873
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
2874
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
2875
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
2876
    },
2877
    {
2878
        /* XXX: Replace with real values */
2879
        .name = "TI SuperSparc II",
2880
        .iu_version = 0x40000000,
2881
        .fpu_version = 0x00000000,
2882
        .mmu_version = 0x00000000,
2883
    },
2884
#endif
2885
};
2886

    
2887
int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
2888
{
2889
    int ret;
2890
    unsigned int i;
2891

    
2892
    ret = -1;
2893
    *def = NULL;
2894
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2895
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
2896
            *def = &sparc_defs[i];
2897
            ret = 0;
2898
            break;
2899
        }
2900
    }
2901

    
2902
    return ret;
2903
}
2904

    
2905
void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2906
{
2907
    unsigned int i;
2908

    
2909
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2910
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
2911
                       sparc_defs[i].name,
2912
                       sparc_defs[i].iu_version,
2913
                       sparc_defs[i].fpu_version,
2914
                       sparc_defs[i].mmu_version);
2915
    }
2916
}
2917

    
2918
int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
2919
{
2920
    env->version = def->iu_version;
2921
    env->fsr = def->fpu_version;
2922
#if !defined(TARGET_SPARC64)
2923
    env->mmuregs[0] = def->mmu_version;
2924
#endif
2925
    return 0;
2926
}
2927

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

    
2930
void cpu_dump_state(CPUState *env, FILE *f, 
2931
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2932
                    int flags)
2933
{
2934
    int i, x;
2935

    
2936
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
2937
    cpu_fprintf(f, "General Registers:\n");
2938
    for (i = 0; i < 4; i++)
2939
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2940
    cpu_fprintf(f, "\n");
2941
    for (; i < 8; i++)
2942
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2943
    cpu_fprintf(f, "\nCurrent Register Window:\n");
2944
    for (x = 0; x < 3; x++) {
2945
        for (i = 0; i < 4; i++)
2946
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2947
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
2948
                    env->regwptr[i + x * 8]);
2949
        cpu_fprintf(f, "\n");
2950
        for (; i < 8; i++)
2951
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2952
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
2953
                    env->regwptr[i + x * 8]);
2954
        cpu_fprintf(f, "\n");
2955
    }
2956
    cpu_fprintf(f, "\nFloating Point Registers:\n");
2957
    for (i = 0; i < 32; i++) {
2958
        if ((i & 3) == 0)
2959
            cpu_fprintf(f, "%%f%02d:", i);
2960
        cpu_fprintf(f, " %016lf", env->fpr[i]);
2961
        if ((i & 3) == 3)
2962
            cpu_fprintf(f, "\n");
2963
    }
2964
#ifdef TARGET_SPARC64
2965
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
2966
                env->pstate, GET_CCR(env), env->asi, env->tl);
2967
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
2968
                env->cansave, env->canrestore, env->otherwin, env->wstate,
2969
                env->cleanwin, NWINDOWS - 1 - env->cwp);
2970
#else
2971
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
2972
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
2973
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
2974
            env->psrs?'S':'-', env->psrps?'P':'-', 
2975
            env->psret?'E':'-', env->wim);
2976
#endif
2977
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
2978
}
2979

    
2980
#if defined(CONFIG_USER_ONLY)
2981
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2982
{
2983
    return addr;
2984
}
2985

    
2986
#else
2987
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
2988
                                 int *access_index, target_ulong address, int rw,
2989
                                 int is_user);
2990

    
2991
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2992
{
2993
    target_phys_addr_t phys_addr;
2994
    int prot, access_index;
2995

    
2996
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
2997
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
2998
            return -1;
2999
    return phys_addr;
3000
}
3001
#endif
3002

    
3003
void helper_flush(target_ulong addr)
3004
{
3005
    addr &= ~7;
3006
    tb_invalidate_page_range(addr, addr + 8);
3007
}