Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ 417454b0

History | View | Annotate | Download (80.4 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 & 0x1e)
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

    
947
static GenOpFunc * const gen_fcmpes[4] = {
948
    gen_op_fcmpes,
949
    gen_op_fcmpes_fcc1,
950
    gen_op_fcmpes_fcc2,
951
    gen_op_fcmpes_fcc3,
952
};
953

    
954
static GenOpFunc * const gen_fcmped[4] = {
955
    gen_op_fcmped,
956
    gen_op_fcmped_fcc1,
957
    gen_op_fcmped_fcc2,
958
    gen_op_fcmped_fcc3,
959
};
960

    
961
#endif
962

    
963
static int gen_trap_ifnofpu(DisasContext * dc)
964
{
965
#if !defined(CONFIG_USER_ONLY)
966
    if (!dc->fpu_enabled) {
967
        save_state(dc);
968
        gen_op_exception(TT_NFPU_INSN);
969
        dc->is_br = 1;
970
        return 1;
971
    }
972
#endif
973
    return 0;
974
}
975

    
976
/* before an instruction, dc->pc must be static */
977
static void disas_sparc_insn(DisasContext * dc)
978
{
979
    unsigned int insn, opc, rs1, rs2, rd;
980

    
981
    insn = ldl_code(dc->pc);
982
    opc = GET_FIELD(insn, 0, 1);
983

    
984
    rd = GET_FIELD(insn, 2, 6);
985
    switch (opc) {
986
    case 0:                        /* branches/sethi */
987
        {
988
            unsigned int xop = GET_FIELD(insn, 7, 9);
989
            int32_t target;
990
            switch (xop) {
991
#ifdef TARGET_SPARC64
992
            case 0x1:                /* V9 BPcc */
993
                {
994
                    int cc;
995

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

    
1077
#ifdef TARGET_SPARC64
1078
            if (dc->pc == (uint32_t)dc->pc) {
1079
                gen_op_movl_T0_im(dc->pc);
1080
            } else {
1081
                gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1082
            }
1083
#else
1084
            gen_op_movl_T0_im(dc->pc);
1085
#endif
1086
            gen_movl_T0_reg(15);
1087
            target += dc->pc;
1088
            gen_mov_pc_npc(dc);
1089
            dc->npc = target;
1090
        }
1091
        goto jmp_insn;
1092
    case 2:                        /* FPU & Logical Operations */
1093
        {
1094
            unsigned int xop = GET_FIELD(insn, 7, 12);
1095
            if (xop == 0x3a) {        /* generate trap */
1096
                int cond;
1097

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

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

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

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

    
2465
#ifndef TARGET_SPARC64
2466
                case 0x30: /* ldc */
2467
                case 0x31: /* ldcsr */
2468
                case 0x33: /* lddc */
2469
                    goto ncp_insn;
2470
                    /* avoid warnings */
2471
                    (void) &gen_op_stfa;
2472
                    (void) &gen_op_stdfa;
2473
                    (void) &gen_op_ldfa;
2474
                    (void) &gen_op_lddfa;
2475
#else
2476
#if !defined(CONFIG_USER_ONLY)
2477
                    (void) &gen_op_cas;
2478
                    (void) &gen_op_casx;
2479
#endif
2480
#endif
2481
#endif
2482
#ifdef TARGET_SPARC64
2483
                case 0x08: /* V9 ldsw */
2484
                    gen_op_ldst(ldsw);
2485
                    break;
2486
                case 0x0b: /* V9 ldx */
2487
                    gen_op_ldst(ldx);
2488
                    break;
2489
                case 0x18: /* V9 ldswa */
2490
                    gen_op_ldswa(insn, 1, 4, 1);
2491
                    break;
2492
                case 0x1b: /* V9 ldxa */
2493
                    gen_op_ldxa(insn, 1, 8, 0);
2494
                    break;
2495
                case 0x2d: /* V9 prefetch, no effect */
2496
                    goto skip_move;
2497
                case 0x30: /* V9 ldfa */
2498
                    gen_op_ldfa(insn, 1, 8, 0); // XXX
2499
                    break;
2500
                case 0x33: /* V9 lddfa */
2501
                    gen_op_lddfa(insn, 1, 8, 0); // XXX
2502

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

    
2717
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2718
                                                 int spc, CPUSPARCState *env)
2719
{
2720
    target_ulong pc_start, last_pc;
2721
    uint16_t *gen_opc_end;
2722
    DisasContext dc1, *dc = &dc1;
2723
    int j, lj = -1;
2724

    
2725
    memset(dc, 0, sizeof(DisasContext));
2726
    dc->tb = tb;
2727
    pc_start = tb->pc;
2728
    dc->pc = pc_start;
2729
    last_pc = dc->pc;
2730
    dc->npc = (target_ulong) tb->cs_base;
2731
#if defined(CONFIG_USER_ONLY)
2732
    dc->mem_idx = 0;
2733
    dc->fpu_enabled = 1;
2734
#else
2735
    dc->mem_idx = ((env->psrs) != 0);
2736
#ifdef TARGET_SPARC64
2737
    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
2738
#else
2739
    dc->fpu_enabled = ((env->psref) != 0);
2740
#endif
2741
#endif
2742
    gen_opc_ptr = gen_opc_buf;
2743
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2744
    gen_opparam_ptr = gen_opparam_buf;
2745
    nb_gen_labels = 0;
2746

    
2747
    do {
2748
        if (env->nb_breakpoints > 0) {
2749
            for(j = 0; j < env->nb_breakpoints; j++) {
2750
                if (env->breakpoints[j] == dc->pc) {
2751
                    if (dc->pc != pc_start)
2752
                        save_state(dc);
2753
                    gen_op_debug();
2754
                    gen_op_movl_T0_0();
2755
                    gen_op_exit_tb();
2756
                    dc->is_br = 1;
2757
                    goto exit_gen_loop;
2758
                }
2759
            }
2760
        }
2761
        if (spc) {
2762
            if (loglevel > 0)
2763
                fprintf(logfile, "Search PC...\n");
2764
            j = gen_opc_ptr - gen_opc_buf;
2765
            if (lj < j) {
2766
                lj++;
2767
                while (lj < j)
2768
                    gen_opc_instr_start[lj++] = 0;
2769
                gen_opc_pc[lj] = dc->pc;
2770
                gen_opc_npc[lj] = dc->npc;
2771
                gen_opc_instr_start[lj] = 1;
2772
            }
2773
        }
2774
        last_pc = dc->pc;
2775
        disas_sparc_insn(dc);
2776

    
2777
        if (dc->is_br)
2778
            break;
2779
        /* if the next PC is different, we abort now */
2780
        if (dc->pc != (last_pc + 4))
2781
            break;
2782
        /* if we reach a page boundary, we stop generation so that the
2783
           PC of a TT_TFAULT exception is always in the right page */
2784
        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
2785
            break;
2786
        /* if single step mode, we generate only one instruction and
2787
           generate an exception */
2788
        if (env->singlestep_enabled) {
2789
            gen_jmp_im(dc->pc);
2790
            gen_op_movl_T0_0();
2791
            gen_op_exit_tb();
2792
            break;
2793
        }
2794
    } while ((gen_opc_ptr < gen_opc_end) &&
2795
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2796

    
2797
 exit_gen_loop:
2798
    if (!dc->is_br) {
2799
        if (dc->pc != DYNAMIC_PC && 
2800
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2801
            /* static PC and NPC: we can use direct chaining */
2802
            gen_branch(dc, (long)tb, dc->pc, dc->npc);
2803
        } else {
2804
            if (dc->pc != DYNAMIC_PC)
2805
                gen_jmp_im(dc->pc);
2806
            save_npc(dc);
2807
            gen_op_movl_T0_0();
2808
            gen_op_exit_tb();
2809
        }
2810
    }
2811
    *gen_opc_ptr = INDEX_op_end;
2812
    if (spc) {
2813
        j = gen_opc_ptr - gen_opc_buf;
2814
        lj++;
2815
        while (lj <= j)
2816
            gen_opc_instr_start[lj++] = 0;
2817
        tb->size = 0;
2818
#if 0
2819
        if (loglevel > 0) {
2820
            page_dump(logfile);
2821
        }
2822
#endif
2823
        gen_opc_jump_pc[0] = dc->jump_pc[0];
2824
        gen_opc_jump_pc[1] = dc->jump_pc[1];
2825
    } else {
2826
        tb->size = last_pc + 4 - pc_start;
2827
    }
2828
#ifdef DEBUG_DISAS
2829
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2830
        fprintf(logfile, "--------------\n");
2831
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2832
        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2833
        fprintf(logfile, "\n");
2834
        if (loglevel & CPU_LOG_TB_OP) {
2835
            fprintf(logfile, "OP:\n");
2836
            dump_ops(gen_opc_buf, gen_opparam_buf);
2837
            fprintf(logfile, "\n");
2838
        }
2839
    }
2840
#endif
2841
    return 0;
2842
}
2843

    
2844
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2845
{
2846
    return gen_intermediate_code_internal(tb, 0, env);
2847
}
2848

    
2849
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2850
{
2851
    return gen_intermediate_code_internal(tb, 1, env);
2852
}
2853

    
2854
extern int ram_size;
2855

    
2856
void cpu_reset(CPUSPARCState *env)
2857
{
2858
    memset(env, 0, sizeof(*env));
2859
    tlb_flush(env, 1);
2860
    env->cwp = 0;
2861
    env->wim = 1;
2862
    env->regwptr = env->regbase + (env->cwp * 16);
2863
#if defined(CONFIG_USER_ONLY)
2864
    env->user_mode_only = 1;
2865
#ifdef TARGET_SPARC64
2866
    env->cleanwin = NWINDOWS - 1;
2867
    env->cansave = NWINDOWS - 1;
2868
#endif
2869
#else
2870
    env->psrs = 1;
2871
    env->psrps = 1;
2872
    env->gregs[1] = ram_size;
2873
#ifdef TARGET_SPARC64
2874
    env->pstate = PS_PRIV;
2875
    env->pc = 0x1fff0000000ULL;
2876
#else
2877
    env->pc = 0xffd00000;
2878
#endif
2879
    env->npc = env->pc + 4;
2880
#endif
2881
}
2882

    
2883
CPUSPARCState *cpu_sparc_init(void)
2884
{
2885
    CPUSPARCState *env;
2886

    
2887
    env = qemu_mallocz(sizeof(CPUSPARCState));
2888
    if (!env)
2889
        return NULL;
2890
    cpu_exec_init(env);
2891
    cpu_reset(env);
2892
    return (env);
2893
}
2894

    
2895
static const sparc_def_t sparc_defs[] = {
2896
#ifdef TARGET_SPARC64
2897
    {
2898
        .name = "TI UltraSparc II",
2899
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
2900
                       | (MAXTL << 8) | (NWINDOWS - 1)),
2901
        .fpu_version = 0x00000000,
2902
        .mmu_version = 0,
2903
    },
2904
#else
2905
    {
2906
        .name = "Fujitsu MB86904",
2907
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
2908
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
2909
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
2910
    },
2911
    {
2912
        /* XXX: Replace with real values */
2913
        .name = "TI SuperSparc II",
2914
        .iu_version = 0x40000000,
2915
        .fpu_version = 0x00000000,
2916
        .mmu_version = 0x00000000,
2917
    },
2918
#endif
2919
};
2920

    
2921
int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
2922
{
2923
    int ret;
2924
    unsigned int i;
2925

    
2926
    ret = -1;
2927
    *def = NULL;
2928
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2929
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
2930
            *def = &sparc_defs[i];
2931
            ret = 0;
2932
            break;
2933
        }
2934
    }
2935

    
2936
    return ret;
2937
}
2938

    
2939
void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2940
{
2941
    unsigned int i;
2942

    
2943
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
2944
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
2945
                       sparc_defs[i].name,
2946
                       sparc_defs[i].iu_version,
2947
                       sparc_defs[i].fpu_version,
2948
                       sparc_defs[i].mmu_version);
2949
    }
2950
}
2951

    
2952
int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
2953
{
2954
    env->version = def->iu_version;
2955
    env->fsr = def->fpu_version;
2956
#if !defined(TARGET_SPARC64)
2957
    env->mmuregs[0] = def->mmu_version;
2958
#endif
2959
    return 0;
2960
}
2961

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

    
2964
void cpu_dump_state(CPUState *env, FILE *f, 
2965
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2966
                    int flags)
2967
{
2968
    int i, x;
2969

    
2970
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
2971
    cpu_fprintf(f, "General Registers:\n");
2972
    for (i = 0; i < 4; i++)
2973
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2974
    cpu_fprintf(f, "\n");
2975
    for (; i < 8; i++)
2976
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2977
    cpu_fprintf(f, "\nCurrent Register Window:\n");
2978
    for (x = 0; x < 3; x++) {
2979
        for (i = 0; i < 4; i++)
2980
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2981
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
2982
                    env->regwptr[i + x * 8]);
2983
        cpu_fprintf(f, "\n");
2984
        for (; i < 8; i++)
2985
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2986
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
2987
                    env->regwptr[i + x * 8]);
2988
        cpu_fprintf(f, "\n");
2989
    }
2990
    cpu_fprintf(f, "\nFloating Point Registers:\n");
2991
    for (i = 0; i < 32; i++) {
2992
        if ((i & 3) == 0)
2993
            cpu_fprintf(f, "%%f%02d:", i);
2994
        cpu_fprintf(f, " %016lf", env->fpr[i]);
2995
        if ((i & 3) == 3)
2996
            cpu_fprintf(f, "\n");
2997
    }
2998
#ifdef TARGET_SPARC64
2999
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
3000
                env->pstate, GET_CCR(env), env->asi, env->tl);
3001
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
3002
                env->cansave, env->canrestore, env->otherwin, env->wstate,
3003
                env->cleanwin, NWINDOWS - 1 - env->cwp);
3004
#else
3005
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
3006
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
3007
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
3008
            env->psrs?'S':'-', env->psrps?'P':'-', 
3009
            env->psret?'E':'-', env->wim);
3010
#endif
3011
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
3012
}
3013

    
3014
#if defined(CONFIG_USER_ONLY)
3015
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
3016
{
3017
    return addr;
3018
}
3019

    
3020
#else
3021
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
3022
                                 int *access_index, target_ulong address, int rw,
3023
                                 int is_user);
3024

    
3025
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
3026
{
3027
    target_phys_addr_t phys_addr;
3028
    int prot, access_index;
3029

    
3030
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
3031
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
3032
            return -1;
3033
    return phys_addr;
3034
}
3035
#endif
3036

    
3037
void helper_flush(target_ulong addr)
3038
{
3039
    addr &= ~7;
3040
    tb_invalidate_page_range(addr, addr + 8);
3041
}