Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ 977d5710

History | View | Annotate | Download (42.6 kB)

1
/*
2
   SPARC translation
3

4
   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5
   Copyright (C) 2003 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
   NPC/PC static optimisations (use JUMP_TB when possible)
26
   FPU-Instructions
27
   Privileged instructions
28
   Coprocessor-Instructions
29
   Optimize synthetic instructions
30
   Optional alignment and privileged instruction check
31
*/
32

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

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

    
43
#define DEBUG_DISAS
44

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

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

    
58
static uint16_t *gen_opc_ptr;
59
static uint32_t *gen_opparam_ptr;
60
extern FILE *logfile;
61
extern int loglevel;
62

    
63
enum {
64
#define DEF(s,n,copy_size) INDEX_op_ ## s,
65
#include "opc.h"
66
#undef DEF
67
    NB_OPS
68
};
69

    
70
#include "gen-op.h"
71

    
72
#define GET_FIELD(X, FROM, TO) \
73
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
74

    
75
#define IS_IMM (insn & (1<<13))
76

    
77
static void disas_sparc_insn(DisasContext * dc);
78

    
79
static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
80
    {
81
     gen_op_movl_g0_T0,
82
     gen_op_movl_g1_T0,
83
     gen_op_movl_g2_T0,
84
     gen_op_movl_g3_T0,
85
     gen_op_movl_g4_T0,
86
     gen_op_movl_g5_T0,
87
     gen_op_movl_g6_T0,
88
     gen_op_movl_g7_T0,
89
     gen_op_movl_o0_T0,
90
     gen_op_movl_o1_T0,
91
     gen_op_movl_o2_T0,
92
     gen_op_movl_o3_T0,
93
     gen_op_movl_o4_T0,
94
     gen_op_movl_o5_T0,
95
     gen_op_movl_o6_T0,
96
     gen_op_movl_o7_T0,
97
     gen_op_movl_l0_T0,
98
     gen_op_movl_l1_T0,
99
     gen_op_movl_l2_T0,
100
     gen_op_movl_l3_T0,
101
     gen_op_movl_l4_T0,
102
     gen_op_movl_l5_T0,
103
     gen_op_movl_l6_T0,
104
     gen_op_movl_l7_T0,
105
     gen_op_movl_i0_T0,
106
     gen_op_movl_i1_T0,
107
     gen_op_movl_i2_T0,
108
     gen_op_movl_i3_T0,
109
     gen_op_movl_i4_T0,
110
     gen_op_movl_i5_T0,
111
     gen_op_movl_i6_T0,
112
     gen_op_movl_i7_T0,
113
     },
114
    {
115
     gen_op_movl_g0_T1,
116
     gen_op_movl_g1_T1,
117
     gen_op_movl_g2_T1,
118
     gen_op_movl_g3_T1,
119
     gen_op_movl_g4_T1,
120
     gen_op_movl_g5_T1,
121
     gen_op_movl_g6_T1,
122
     gen_op_movl_g7_T1,
123
     gen_op_movl_o0_T1,
124
     gen_op_movl_o1_T1,
125
     gen_op_movl_o2_T1,
126
     gen_op_movl_o3_T1,
127
     gen_op_movl_o4_T1,
128
     gen_op_movl_o5_T1,
129
     gen_op_movl_o6_T1,
130
     gen_op_movl_o7_T1,
131
     gen_op_movl_l0_T1,
132
     gen_op_movl_l1_T1,
133
     gen_op_movl_l2_T1,
134
     gen_op_movl_l3_T1,
135
     gen_op_movl_l4_T1,
136
     gen_op_movl_l5_T1,
137
     gen_op_movl_l6_T1,
138
     gen_op_movl_l7_T1,
139
     gen_op_movl_i0_T1,
140
     gen_op_movl_i1_T1,
141
     gen_op_movl_i2_T1,
142
     gen_op_movl_i3_T1,
143
     gen_op_movl_i4_T1,
144
     gen_op_movl_i5_T1,
145
     gen_op_movl_i6_T1,
146
     gen_op_movl_i7_T1,
147
     }
148
};
149

    
150
static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
151
    {
152
     gen_op_movl_T0_g0,
153
     gen_op_movl_T0_g1,
154
     gen_op_movl_T0_g2,
155
     gen_op_movl_T0_g3,
156
     gen_op_movl_T0_g4,
157
     gen_op_movl_T0_g5,
158
     gen_op_movl_T0_g6,
159
     gen_op_movl_T0_g7,
160
     gen_op_movl_T0_o0,
161
     gen_op_movl_T0_o1,
162
     gen_op_movl_T0_o2,
163
     gen_op_movl_T0_o3,
164
     gen_op_movl_T0_o4,
165
     gen_op_movl_T0_o5,
166
     gen_op_movl_T0_o6,
167
     gen_op_movl_T0_o7,
168
     gen_op_movl_T0_l0,
169
     gen_op_movl_T0_l1,
170
     gen_op_movl_T0_l2,
171
     gen_op_movl_T0_l3,
172
     gen_op_movl_T0_l4,
173
     gen_op_movl_T0_l5,
174
     gen_op_movl_T0_l6,
175
     gen_op_movl_T0_l7,
176
     gen_op_movl_T0_i0,
177
     gen_op_movl_T0_i1,
178
     gen_op_movl_T0_i2,
179
     gen_op_movl_T0_i3,
180
     gen_op_movl_T0_i4,
181
     gen_op_movl_T0_i5,
182
     gen_op_movl_T0_i6,
183
     gen_op_movl_T0_i7,
184
     },
185
    {
186
     gen_op_movl_T1_g0,
187
     gen_op_movl_T1_g1,
188
     gen_op_movl_T1_g2,
189
     gen_op_movl_T1_g3,
190
     gen_op_movl_T1_g4,
191
     gen_op_movl_T1_g5,
192
     gen_op_movl_T1_g6,
193
     gen_op_movl_T1_g7,
194
     gen_op_movl_T1_o0,
195
     gen_op_movl_T1_o1,
196
     gen_op_movl_T1_o2,
197
     gen_op_movl_T1_o3,
198
     gen_op_movl_T1_o4,
199
     gen_op_movl_T1_o5,
200
     gen_op_movl_T1_o6,
201
     gen_op_movl_T1_o7,
202
     gen_op_movl_T1_l0,
203
     gen_op_movl_T1_l1,
204
     gen_op_movl_T1_l2,
205
     gen_op_movl_T1_l3,
206
     gen_op_movl_T1_l4,
207
     gen_op_movl_T1_l5,
208
     gen_op_movl_T1_l6,
209
     gen_op_movl_T1_l7,
210
     gen_op_movl_T1_i0,
211
     gen_op_movl_T1_i1,
212
     gen_op_movl_T1_i2,
213
     gen_op_movl_T1_i3,
214
     gen_op_movl_T1_i4,
215
     gen_op_movl_T1_i5,
216
     gen_op_movl_T1_i6,
217
     gen_op_movl_T1_i7,
218
     },
219
    {
220
     gen_op_movl_T2_g0,
221
     gen_op_movl_T2_g1,
222
     gen_op_movl_T2_g2,
223
     gen_op_movl_T2_g3,
224
     gen_op_movl_T2_g4,
225
     gen_op_movl_T2_g5,
226
     gen_op_movl_T2_g6,
227
     gen_op_movl_T2_g7,
228
     gen_op_movl_T2_o0,
229
     gen_op_movl_T2_o1,
230
     gen_op_movl_T2_o2,
231
     gen_op_movl_T2_o3,
232
     gen_op_movl_T2_o4,
233
     gen_op_movl_T2_o5,
234
     gen_op_movl_T2_o6,
235
     gen_op_movl_T2_o7,
236
     gen_op_movl_T2_l0,
237
     gen_op_movl_T2_l1,
238
     gen_op_movl_T2_l2,
239
     gen_op_movl_T2_l3,
240
     gen_op_movl_T2_l4,
241
     gen_op_movl_T2_l5,
242
     gen_op_movl_T2_l6,
243
     gen_op_movl_T2_l7,
244
     gen_op_movl_T2_i0,
245
     gen_op_movl_T2_i1,
246
     gen_op_movl_T2_i2,
247
     gen_op_movl_T2_i3,
248
     gen_op_movl_T2_i4,
249
     gen_op_movl_T2_i5,
250
     gen_op_movl_T2_i6,
251
     gen_op_movl_T2_i7,
252
     }
253
};
254

    
255
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
256
    gen_op_movl_T0_im,
257
    gen_op_movl_T1_im,
258
    gen_op_movl_T2_im
259
};
260

    
261
#define GEN32(func, NAME) \
262
static GenOpFunc *NAME ## _table [32] = {                                     \
263
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
264
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
265
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
266
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
267
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
268
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
269
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
270
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
271
};                                                                            \
272
static inline void func(int n)                                                \
273
{                                                                             \
274
    NAME ## _table[n]();                                                      \
275
}
276

    
277
/* floating point registers moves */
278
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
279
GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
280
GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fprf);
281
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
282
GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
283
GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fprf);
284

    
285
GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
286
GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
287
GEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fprf);
288
GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
289
GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
290
GEN32(gen_op_store_DT2_fpr, gen_op_store_DT2_fpr_fprf);
291

    
292
#if defined(CONFIG_USER_ONLY)
293
#define gen_op_ldst(name)        gen_op_##name##_raw()
294
#define OP_LD_TABLE(width)
295
#define supervisor(dc) 0
296
#else
297
#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
298
#define OP_LD_TABLE(width)                                                      \
299
static GenOpFunc *gen_op_##width[] = {                                        \
300
    &gen_op_##width##_user,                                                   \
301
    &gen_op_##width##_kernel,                                                 \
302
};                                                                            \
303
                                                                              \
304
static void gen_op_##width##a(int insn, int is_ld, int size, int sign)        \
305
{                                                                             \
306
    int asi;                                                                  \
307
                                                                              \
308
    asi = GET_FIELD(insn, 19, 26);                                            \
309
    switch (asi) {                                                            \
310
        case 10: /* User data access */                                       \
311
            gen_op_##width##_user();                                          \
312
            break;                                                            \
313
        case 11: /* Supervisor data access */                                 \
314
            gen_op_##width##_kernel();                                        \
315
            break;                                                            \
316
        case 0x20 ... 0x2f: /* MMU passthrough */                              \
317
            if (is_ld)                                                        \
318
                gen_op_ld_asi(asi, size, sign);                                      \
319
            else                                                              \
320
                gen_op_st_asi(asi, size, sign);                                      \
321
            break;                                                            \
322
        default:                                                              \
323
            if (is_ld)                                                        \
324
                gen_op_ld_asi(asi, size, sign);                                      \
325
            else                                                              \
326
                gen_op_st_asi(asi, size, sign);                                      \
327
            break;                                                            \
328
    }                                                                         \
329
}
330

    
331
#define supervisor(dc) (dc->mem_idx == 1)
332
#endif
333

    
334
OP_LD_TABLE(ld);
335
OP_LD_TABLE(st);
336
OP_LD_TABLE(ldub);
337
OP_LD_TABLE(lduh);
338
OP_LD_TABLE(ldsb);
339
OP_LD_TABLE(ldsh);
340
OP_LD_TABLE(stb);
341
OP_LD_TABLE(sth);
342
OP_LD_TABLE(std);
343
OP_LD_TABLE(ldstub);
344
OP_LD_TABLE(swap);
345
OP_LD_TABLE(ldd);
346
OP_LD_TABLE(stf);
347
OP_LD_TABLE(stdf);
348
OP_LD_TABLE(ldf);
349
OP_LD_TABLE(lddf);
350

    
351
static inline void gen_movl_imm_TN(int reg, int imm)
352
{
353
    gen_op_movl_TN_im[reg] (imm);
354
}
355

    
356
static inline void gen_movl_imm_T1(int val)
357
{
358
    gen_movl_imm_TN(1, val);
359
}
360

    
361
static inline void gen_movl_imm_T0(int val)
362
{
363
    gen_movl_imm_TN(0, val);
364
}
365

    
366
static inline void gen_movl_reg_TN(int reg, int t)
367
{
368
    if (reg)
369
        gen_op_movl_reg_TN[t][reg] ();
370
    else
371
        gen_movl_imm_TN(t, 0);
372
}
373

    
374
static inline void gen_movl_reg_T0(int reg)
375
{
376
    gen_movl_reg_TN(reg, 0);
377
}
378

    
379
static inline void gen_movl_reg_T1(int reg)
380
{
381
    gen_movl_reg_TN(reg, 1);
382
}
383

    
384
static inline void gen_movl_reg_T2(int reg)
385
{
386
    gen_movl_reg_TN(reg, 2);
387
}
388

    
389
static inline void gen_movl_TN_reg(int reg, int t)
390
{
391
    if (reg)
392
        gen_op_movl_TN_reg[t][reg] ();
393
}
394

    
395
static inline void gen_movl_T0_reg(int reg)
396
{
397
    gen_movl_TN_reg(reg, 0);
398
}
399

    
400
static inline void gen_movl_T1_reg(int reg)
401
{
402
    gen_movl_TN_reg(reg, 1);
403
}
404

    
405
/* call this function before using T2 as it may have been set for a jump */
406
static inline void flush_T2(DisasContext * dc)
407
{
408
    if (dc->npc == JUMP_PC) {
409
        gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
410
        dc->npc = DYNAMIC_PC;
411
    }
412
}
413

    
414
static inline void save_npc(DisasContext * dc)
415
{
416
    if (dc->npc == JUMP_PC) {
417
        gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
418
        dc->npc = DYNAMIC_PC;
419
    } else if (dc->npc != DYNAMIC_PC) {
420
        gen_op_movl_npc_im(dc->npc);
421
    }
422
}
423

    
424
static inline void save_state(DisasContext * dc)
425
{
426
    gen_op_jmp_im((uint32_t)dc->pc);
427
    save_npc(dc);
428
}
429

    
430
static void gen_cond(int cond)
431
{
432
        switch (cond) {
433
        case 0x0:
434
            gen_op_movl_T2_0();
435
            break;
436
        case 0x1:
437
            gen_op_eval_be();
438
            break;
439
        case 0x2:
440
            gen_op_eval_ble();
441
            break;
442
        case 0x3:
443
            gen_op_eval_bl();
444
            break;
445
        case 0x4:
446
            gen_op_eval_bleu();
447
            break;
448
        case 0x5:
449
            gen_op_eval_bcs();
450
            break;
451
        case 0x6:
452
            gen_op_eval_bneg();
453
            break;
454
        case 0x7:
455
            gen_op_eval_bvs();
456
            break;
457
        case 0x8:
458
            gen_op_movl_T2_1();
459
            break;
460
        case 0x9:
461
            gen_op_eval_bne();
462
            break;
463
        case 0xa:
464
            gen_op_eval_bg();
465
            break;
466
        case 0xb:
467
            gen_op_eval_bge();
468
            break;
469
        case 0xc:
470
            gen_op_eval_bgu();
471
            break;
472
        case 0xd:
473
            gen_op_eval_bcc();
474
            break;
475
        case 0xe:
476
            gen_op_eval_bpos();
477
            break;
478
        default:
479
        case 0xf:
480
            gen_op_eval_bvc();
481
            break;
482
        }
483
}
484

    
485
static void gen_fcond(int cond)
486
{
487
        switch (cond) {
488
        case 0x0:
489
            gen_op_movl_T2_0();
490
            break;
491
        case 0x1:
492
            gen_op_eval_fbne();
493
            break;
494
        case 0x2:
495
            gen_op_eval_fblg();
496
            break;
497
        case 0x3:
498
            gen_op_eval_fbul();
499
            break;
500
        case 0x4:
501
            gen_op_eval_fbl();
502
            break;
503
        case 0x5:
504
            gen_op_eval_fbug();
505
            break;
506
        case 0x6:
507
            gen_op_eval_fbg();
508
            break;
509
        case 0x7:
510
            gen_op_eval_fbu();
511
            break;
512
        case 0x8:
513
            gen_op_movl_T2_1();
514
            break;
515
        case 0x9:
516
            gen_op_eval_fbe();
517
            break;
518
        case 0xa:
519
            gen_op_eval_fbue();
520
            break;
521
        case 0xb:
522
            gen_op_eval_fbge();
523
            break;
524
        case 0xc:
525
            gen_op_eval_fbuge();
526
            break;
527
        case 0xd:
528
            gen_op_eval_fble();
529
            break;
530
        case 0xe:
531
            gen_op_eval_fbule();
532
            break;
533
        default:
534
        case 0xf:
535
            gen_op_eval_fbo();
536
            break;
537
        }
538
}
539

    
540
static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
541
{
542
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
543
    target += (uint32_t) dc->pc;
544
    if (cond == 0x0) {
545
        /* unconditional not taken */
546
        if (a) {
547
            dc->pc = dc->npc + 4;
548
            dc->npc = dc->pc + 4;
549
        } else {
550
            dc->pc = dc->npc;
551
            dc->npc = dc->pc + 4;
552
        }
553
    } else if (cond == 0x8) {
554
        /* unconditional taken */
555
        if (a) {
556
            dc->pc = target;
557
            dc->npc = dc->pc + 4;
558
        } else {
559
            dc->pc = dc->npc;
560
            dc->npc = target;
561
        }
562
    } else {
563
        flush_T2(dc);
564
        gen_cond(cond);
565
        if (a) {
566
            gen_op_branch_a((long)dc->tb, target, dc->npc);
567
            dc->is_br = 1;
568
        } else {
569
            dc->pc = dc->npc;
570
            dc->jump_pc[0] = target;
571
            dc->jump_pc[1] = dc->npc + 4;
572
            dc->npc = JUMP_PC;
573
        }
574
    }
575
}
576

    
577
static void do_fbranch(DisasContext * dc, uint32_t target, uint32_t insn)
578
{
579
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
580
    target += (uint32_t) dc->pc;
581
    if (cond == 0x0) {
582
        /* unconditional not taken */
583
        if (a) {
584
            dc->pc = dc->npc + 4;
585
            dc->npc = dc->pc + 4;
586
        } else {
587
            dc->pc = dc->npc;
588
            dc->npc = dc->pc + 4;
589
        }
590
    } else if (cond == 0x8) {
591
        /* unconditional taken */
592
        if (a) {
593
            dc->pc = target;
594
            dc->npc = dc->pc + 4;
595
        } else {
596
            dc->pc = dc->npc;
597
            dc->npc = target;
598
        }
599
    } else {
600
        flush_T2(dc);
601
        gen_fcond(cond);
602
        if (a) {
603
            gen_op_branch_a((long)dc->tb, target, dc->npc);
604
            dc->is_br = 1;
605
        } else {
606
            dc->pc = dc->npc;
607
            dc->jump_pc[0] = target;
608
            dc->jump_pc[1] = dc->npc + 4;
609
            dc->npc = JUMP_PC;
610
        }
611
    }
612
}
613

    
614
#if 0
615
static void gen_debug(DisasContext *s, uint32_t pc)
616
{
617
    gen_op_jmp_im(pc);
618
    gen_op_debug();
619
    s->is_br = 1;
620
}
621
#endif
622

    
623
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
624

    
625
static int sign_extend(int x, int len)
626
{
627
    len = 32 - len;
628
    return (x << len) >> len;
629
}
630

    
631
static void disas_sparc_insn(DisasContext * dc)
632
{
633
    unsigned int insn, opc, rs1, rs2, rd;
634

    
635
    insn = ldl_code(dc->pc);
636
    opc = GET_FIELD(insn, 0, 1);
637

    
638
    rd = GET_FIELD(insn, 2, 6);
639
    switch (opc) {
640
    case 0:                        /* branches/sethi */
641
        {
642
            unsigned int xop = GET_FIELD(insn, 7, 9);
643
            int target;
644
            target = GET_FIELD(insn, 10, 31);
645
            switch (xop) {
646
            case 0x0:
647
            case 0x1:                /* UNIMPL */
648
            case 0x5:                /*CBN+x */
649
            default:
650
                goto illegal_insn;
651
            case 0x2:                /* BN+x */
652
                {
653
                    target <<= 2;
654
                    target = sign_extend(target, 22);
655
                    do_branch(dc, target, insn);
656
                    goto jmp_insn;
657
                }
658
            case 0x6:                /* FBN+x */
659
                {
660
#if !defined(CONFIG_USER_ONLY)
661
                    gen_op_trap_ifnofpu();
662
#endif
663
                    target <<= 2;
664
                    target = sign_extend(target, 22);
665
                    do_fbranch(dc, target, insn);
666
                    goto jmp_insn;
667
                }
668
            case 0x4:                /* SETHI */
669
#define OPTIM
670
#if defined(OPTIM)
671
                if (rd) { // nop
672
#endif
673
                    gen_movl_imm_T0(target << 10);
674
                    gen_movl_T0_reg(rd);
675
#if defined(OPTIM)
676
                }
677
#endif
678
                break;
679
            }
680
            break;
681
        }
682
    case 1:
683
        /*CALL*/ {
684
            unsigned int target = GET_FIELDs(insn, 2, 31) << 2;
685

    
686
            gen_op_movl_T0_im((long) (dc->pc));
687
            gen_movl_T0_reg(15);
688
            target = dc->pc + target;
689
            dc->pc = dc->npc;
690
            dc->npc = target;
691
        }
692
        goto jmp_insn;
693
    case 2:                        /* FPU & Logical Operations */
694
        {
695
            unsigned int xop = GET_FIELD(insn, 7, 12);
696
            if (xop == 0x3a) {        /* generate trap */
697
                int cond;
698
                rs1 = GET_FIELD(insn, 13, 17);
699
                gen_movl_reg_T0(rs1);
700
                if (IS_IMM) {
701
                    rs2 = GET_FIELD(insn, 25, 31);
702
#if defined(OPTIM)
703
                    if (rs2 != 0) {
704
#endif
705
                        gen_movl_imm_T1(rs2);
706
                        gen_op_add_T1_T0();
707
#if defined(OPTIM)
708
                    }
709
#endif
710
                } else {
711
                    rs2 = GET_FIELD(insn, 27, 31);
712
#if defined(OPTIM)
713
                    if (rs2 != 0) {
714
#endif
715
                        gen_movl_reg_T1(rs2);
716
                        gen_op_add_T1_T0();
717
#if defined(OPTIM)
718
                    }
719
#endif
720
                }
721
                save_state(dc);
722
                cond = GET_FIELD(insn, 3, 6);
723
                if (cond == 0x8) {
724
                    gen_op_trap_T0();
725
                    dc->is_br = 1;
726
                    goto jmp_insn;
727
                } else {
728
                    gen_cond(cond);
729
                    gen_op_trapcc_T0();
730
                }
731
            } else if (xop == 0x28) {
732
                rs1 = GET_FIELD(insn, 13, 17);
733
                switch(rs1) {
734
                case 0: /* rdy */
735
                    gen_op_rdy();
736
                    gen_movl_T0_reg(rd);
737
                    break;
738
                case 15: /* stbar */
739
                    break; /* no effect? */
740
                default:
741
                    goto illegal_insn;
742
                }
743
#if !defined(CONFIG_USER_ONLY)
744
            } else if (xop == 0x29) {
745
                if (!supervisor(dc))
746
                    goto priv_insn;
747
                gen_op_rdpsr();
748
                gen_movl_T0_reg(rd);
749
                break;
750
            } else if (xop == 0x2a) {
751
                if (!supervisor(dc))
752
                    goto priv_insn;
753
                gen_op_rdwim();
754
                gen_movl_T0_reg(rd);
755
                break;
756
            } else if (xop == 0x2b) {
757
                if (!supervisor(dc))
758
                    goto priv_insn;
759
                gen_op_rdtbr();
760
                gen_movl_T0_reg(rd);
761
                break;
762
#endif
763
            } else if (xop == 0x34) {        /* FPU Operations */
764
#if !defined(CONFIG_USER_ONLY)
765
                gen_op_trap_ifnofpu();
766
#endif
767
                rs1 = GET_FIELD(insn, 13, 17);
768
                rs2 = GET_FIELD(insn, 27, 31);
769
                xop = GET_FIELD(insn, 18, 26);
770
                switch (xop) {
771
                    case 0x1: /* fmovs */
772
                        gen_op_load_fpr_FT0(rs2);
773
                        gen_op_store_FT0_fpr(rd);
774
                        break;
775
                    case 0x5: /* fnegs */
776
                        gen_op_load_fpr_FT1(rs2);
777
                        gen_op_fnegs();
778
                        gen_op_store_FT0_fpr(rd);
779
                        break;
780
                    case 0x9: /* fabss */
781
                        gen_op_load_fpr_FT1(rs2);
782
                        gen_op_fabss();
783
                        gen_op_store_FT0_fpr(rd);
784
                        break;
785
                    case 0x29: /* fsqrts */
786
                        gen_op_load_fpr_FT1(rs2);
787
                        gen_op_fsqrts();
788
                        gen_op_store_FT0_fpr(rd);
789
                        break;
790
                    case 0x2a: /* fsqrtd */
791
                        gen_op_load_fpr_DT1(rs2);
792
                        gen_op_fsqrtd();
793
                        gen_op_store_DT0_fpr(rd);
794
                        break;
795
                    case 0x2b: /* fsqrtq */
796
                        goto nfpu_insn;
797
                    case 0x41:
798
                        gen_op_load_fpr_FT0(rs1);
799
                        gen_op_load_fpr_FT1(rs2);
800
                        gen_op_fadds();
801
                        gen_op_store_FT0_fpr(rd);
802
                        break;
803
                    case 0x42:
804
                        gen_op_load_fpr_DT0(rs1);
805
                        gen_op_load_fpr_DT1(rs2);
806
                        gen_op_faddd();
807
                        gen_op_store_DT0_fpr(rd);
808
                        break;
809
                    case 0x43: /* faddq */
810
                        goto nfpu_insn;
811
                    case 0x45:
812
                        gen_op_load_fpr_FT0(rs1);
813
                        gen_op_load_fpr_FT1(rs2);
814
                        gen_op_fsubs();
815
                        gen_op_store_FT0_fpr(rd);
816
                        break;
817
                    case 0x46:
818
                        gen_op_load_fpr_DT0(rs1);
819
                        gen_op_load_fpr_DT1(rs2);
820
                        gen_op_fsubd();
821
                        gen_op_store_DT0_fpr(rd);
822
                        break;
823
                    case 0x47: /* fsubq */
824
                        goto nfpu_insn;
825
                    case 0x49:
826
                        gen_op_load_fpr_FT0(rs1);
827
                        gen_op_load_fpr_FT1(rs2);
828
                        gen_op_fmuls();
829
                        gen_op_store_FT0_fpr(rd);
830
                        break;
831
                    case 0x4a:
832
                        gen_op_load_fpr_DT0(rs1);
833
                        gen_op_load_fpr_DT1(rs2);
834
                        gen_op_fmuld();
835
                        gen_op_store_DT0_fpr(rd);
836
                        break;
837
                    case 0x4b: /* fmulq */
838
                        goto nfpu_insn;
839
                    case 0x4d:
840
                        gen_op_load_fpr_FT0(rs1);
841
                        gen_op_load_fpr_FT1(rs2);
842
                        gen_op_fdivs();
843
                        gen_op_store_FT0_fpr(rd);
844
                        break;
845
                    case 0x4e:
846
                        gen_op_load_fpr_DT0(rs1);
847
                        gen_op_load_fpr_DT1(rs2);
848
                        gen_op_fdivd();
849
                        gen_op_store_DT0_fpr(rd);
850
                        break;
851
                    case 0x4f: /* fdivq */
852
                        goto nfpu_insn;
853
                    case 0x69:
854
                        gen_op_load_fpr_FT0(rs1);
855
                        gen_op_load_fpr_FT1(rs2);
856
                        gen_op_fsmuld();
857
                        gen_op_store_DT0_fpr(rd);
858
                        break;
859
                    case 0x6e: /* fdmulq */
860
                        goto nfpu_insn;
861
                    case 0xc4:
862
                        gen_op_load_fpr_FT1(rs2);
863
                        gen_op_fitos();
864
                        gen_op_store_FT0_fpr(rd);
865
                        break;
866
                    case 0xc6:
867
                        gen_op_load_fpr_DT1(rs2);
868
                        gen_op_fdtos();
869
                        gen_op_store_FT0_fpr(rd);
870
                        break;
871
                    case 0xc7: /* fqtos */
872
                        goto nfpu_insn;
873
                    case 0xc8:
874
                        gen_op_load_fpr_FT1(rs2);
875
                        gen_op_fitod();
876
                        gen_op_store_DT0_fpr(rd);
877
                        break;
878
                    case 0xc9:
879
                        gen_op_load_fpr_FT1(rs2);
880
                        gen_op_fstod();
881
                        gen_op_store_DT0_fpr(rd);
882
                        break;
883
                    case 0xcb: /* fqtod */
884
                        goto nfpu_insn;
885
                    case 0xcc: /* fitoq */
886
                        goto nfpu_insn;
887
                    case 0xcd: /* fstoq */
888
                        goto nfpu_insn;
889
                    case 0xce: /* fdtoq */
890
                        goto nfpu_insn;
891
                    case 0xd1:
892
                        gen_op_load_fpr_FT1(rs2);
893
                        gen_op_fstoi();
894
                        gen_op_store_FT0_fpr(rd);
895
                        break;
896
                    case 0xd2:
897
                        gen_op_load_fpr_DT1(rs2);
898
                        gen_op_fdtoi();
899
                        gen_op_store_FT0_fpr(rd);
900
                        break;
901
                    case 0xd3: /* fqtoi */
902
                        goto nfpu_insn;
903
                    default:
904
                        goto illegal_insn;
905
                }
906
            } else if (xop == 0x35) {        /* FPU Operations */
907
#if !defined(CONFIG_USER_ONLY)
908
                gen_op_trap_ifnofpu();
909
#endif
910
                rs1 = GET_FIELD(insn, 13, 17);
911
                rs2 = GET_FIELD(insn, 27, 31);
912
                xop = GET_FIELD(insn, 18, 26);
913
                switch (xop) {
914
                    case 0x51:
915
                        gen_op_load_fpr_FT0(rs1);
916
                        gen_op_load_fpr_FT1(rs2);
917
                        gen_op_fcmps();
918
                        break;
919
                    case 0x52:
920
                        gen_op_load_fpr_DT0(rs1);
921
                        gen_op_load_fpr_DT1(rs2);
922
                        gen_op_fcmpd();
923
                        break;
924
                    case 0x53: /* fcmpq */
925
                        goto nfpu_insn;
926
                    case 0x55: /* fcmpes */
927
                        gen_op_load_fpr_FT0(rs1);
928
                        gen_op_load_fpr_FT1(rs2);
929
                        gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */
930
                        break;
931
                    case 0x56: /* fcmped */
932
                        gen_op_load_fpr_DT0(rs1);
933
                        gen_op_load_fpr_DT1(rs2);
934
                        gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */
935
                        break;
936
                    case 0x57: /* fcmpeq */
937
                        goto nfpu_insn;
938
                    default:
939
                        goto illegal_insn;
940
                }
941
#if defined(OPTIM)
942
            } else if (xop == 0x2) {
943
                // clr/mov shortcut
944

    
945
                rs1 = GET_FIELD(insn, 13, 17);
946
                if (rs1 == 0) {
947
                    // or %g0, x, y -> mov T1, x; mov y, T1
948
                    if (IS_IMM) {        /* immediate */
949
                        rs2 = GET_FIELDs(insn, 19, 31);
950
                        gen_movl_imm_T1(rs2);
951
                    } else {                /* register */
952
                        rs2 = GET_FIELD(insn, 27, 31);
953
                        gen_movl_reg_T1(rs2);
954
                    }
955
                    gen_movl_T1_reg(rd);
956
                } else {
957
                    gen_movl_reg_T0(rs1);
958
                    if (IS_IMM) {        /* immediate */
959
                        // or x, #0, y -> mov T1, x; mov y, T1
960
                        rs2 = GET_FIELDs(insn, 19, 31);
961
                        if (rs2 != 0) {
962
                            gen_movl_imm_T1(rs2);
963
                            gen_op_or_T1_T0();
964
                        }
965
                    } else {                /* register */
966
                        // or x, %g0, y -> mov T1, x; mov y, T1
967
                        rs2 = GET_FIELD(insn, 27, 31);
968
                        if (rs2 != 0) {
969
                            gen_movl_reg_T1(rs2);
970
                            gen_op_or_T1_T0();
971
                        }
972
                    }
973
                    gen_movl_T0_reg(rd);
974
                }
975
#endif
976
            } else if (xop < 0x38) {
977
                rs1 = GET_FIELD(insn, 13, 17);
978
                gen_movl_reg_T0(rs1);
979
                if (IS_IMM) {        /* immediate */
980
                    rs2 = GET_FIELDs(insn, 19, 31);
981
                    gen_movl_imm_T1(rs2);
982
                } else {                /* register */
983
                    rs2 = GET_FIELD(insn, 27, 31);
984
                    gen_movl_reg_T1(rs2);
985
                }
986
                if (xop < 0x20) {
987
                    switch (xop & ~0x10) {
988
                    case 0x0:
989
                        if (xop & 0x10)
990
                            gen_op_add_T1_T0_cc();
991
                        else
992
                            gen_op_add_T1_T0();
993
                        break;
994
                    case 0x1:
995
                        gen_op_and_T1_T0();
996
                        if (xop & 0x10)
997
                            gen_op_logic_T0_cc();
998
                        break;
999
                    case 0x2:
1000
                        gen_op_or_T1_T0();
1001
                        if (xop & 0x10)
1002
                            gen_op_logic_T0_cc();
1003
                        break;
1004
                    case 0x3:
1005
                        gen_op_xor_T1_T0();
1006
                        if (xop & 0x10)
1007
                            gen_op_logic_T0_cc();
1008
                        break;
1009
                    case 0x4:
1010
                        if (xop & 0x10)
1011
                            gen_op_sub_T1_T0_cc();
1012
                        else
1013
                            gen_op_sub_T1_T0();
1014
                        break;
1015
                    case 0x5:
1016
                        gen_op_andn_T1_T0();
1017
                        if (xop & 0x10)
1018
                            gen_op_logic_T0_cc();
1019
                        break;
1020
                    case 0x6:
1021
                        gen_op_orn_T1_T0();
1022
                        if (xop & 0x10)
1023
                            gen_op_logic_T0_cc();
1024
                        break;
1025
                    case 0x7:
1026
                        gen_op_xnor_T1_T0();
1027
                        if (xop & 0x10)
1028
                            gen_op_logic_T0_cc();
1029
                        break;
1030
                    case 0x8:
1031
                        gen_op_addx_T1_T0();
1032
                        if (xop & 0x10)
1033
                            gen_op_set_flags();
1034
                        break;
1035
                    case 0xa:
1036
                        gen_op_umul_T1_T0();
1037
                        if (xop & 0x10)
1038
                            gen_op_logic_T0_cc();
1039
                        break;
1040
                    case 0xb:
1041
                        gen_op_smul_T1_T0();
1042
                        if (xop & 0x10)
1043
                            gen_op_logic_T0_cc();
1044
                        break;
1045
                    case 0xc:
1046
                        gen_op_subx_T1_T0();
1047
                        if (xop & 0x10)
1048
                            gen_op_set_flags();
1049
                        break;
1050
                    case 0xe:
1051
                        gen_op_udiv_T1_T0();
1052
                        if (xop & 0x10)
1053
                            gen_op_div_cc();
1054
                        break;
1055
                    case 0xf:
1056
                        gen_op_sdiv_T1_T0();
1057
                        if (xop & 0x10)
1058
                            gen_op_div_cc();
1059
                        break;
1060
                    default:
1061
                        goto illegal_insn;
1062
                    }
1063
                    gen_movl_T0_reg(rd);
1064
                } else {
1065
                    switch (xop) {
1066
                    case 0x20: /* taddcc */
1067
                    case 0x21: /* tsubcc */
1068
                    case 0x22: /* taddcctv */
1069
                    case 0x23: /* tsubcctv */
1070
                        goto illegal_insn;
1071
                    case 0x24: /* mulscc */
1072
                        gen_op_mulscc_T1_T0();
1073
                        gen_movl_T0_reg(rd);
1074
                        break;
1075
                    case 0x25:        /* SLL */
1076
                        gen_op_sll();
1077
                        gen_movl_T0_reg(rd);
1078
                        break;
1079
                    case 0x26:
1080
                        gen_op_srl();
1081
                        gen_movl_T0_reg(rd);
1082
                        break;
1083
                    case 0x27:
1084
                        gen_op_sra();
1085
                        gen_movl_T0_reg(rd);
1086
                        break;
1087
                    case 0x30:
1088
                        {
1089
                            gen_op_xor_T1_T0();
1090
                            switch(rd) {
1091
                            case 0:
1092
                                gen_op_wry();
1093
                                break;
1094
                            default:
1095
                                goto illegal_insn;
1096
                            }
1097
                        }
1098
                        break;
1099
#if !defined(CONFIG_USER_ONLY)
1100
                    case 0x31:
1101
                        {
1102
                            if (!supervisor(dc))
1103
                                goto priv_insn;
1104
                            gen_op_xor_T1_T0();
1105
                            gen_op_wrpsr();
1106
                        }
1107
                        break;
1108
                    case 0x32:
1109
                        {
1110
                            if (!supervisor(dc))
1111
                                goto priv_insn;
1112
                            gen_op_xor_T1_T0();
1113
                            gen_op_wrwim();
1114
                        }
1115
                        break;
1116
                    case 0x33:
1117
                        {
1118
                            if (!supervisor(dc))
1119
                                goto priv_insn;
1120
                            gen_op_xor_T1_T0();
1121
                            gen_op_wrtbr();
1122
                        }
1123
                        break;
1124
#endif
1125
                    default:
1126
                        goto illegal_insn;
1127
                    }
1128
                }
1129
            } else {
1130
                rs1 = GET_FIELD(insn, 13, 17);
1131
                gen_movl_reg_T0(rs1);
1132
                if (IS_IMM) {        /* immediate */
1133
                    rs2 = GET_FIELDs(insn, 19, 31);
1134
#if defined(OPTIM)
1135
                    if (rs2) {
1136
#endif
1137
                        gen_movl_imm_T1(rs2);
1138
                        gen_op_add_T1_T0();
1139
#if defined(OPTIM)
1140
                    }
1141
#endif
1142
                } else {                /* register */
1143
                    rs2 = GET_FIELD(insn, 27, 31);
1144
#if defined(OPTIM)
1145
                    if (rs2) {
1146
#endif
1147
                        gen_movl_reg_T1(rs2);
1148
                        gen_op_add_T1_T0();
1149
#if defined(OPTIM)
1150
                    }
1151
#endif
1152
                }
1153
                switch (xop) {
1154
                case 0x38:        /* jmpl */
1155
                    {
1156
                        gen_op_movl_npc_T0();
1157
                        if (rd != 0) {
1158
                            gen_op_movl_T0_im((long) (dc->pc));
1159
                            gen_movl_T0_reg(rd);
1160
                        }
1161
                        dc->pc = dc->npc;
1162
                        dc->npc = DYNAMIC_PC;
1163
                    }
1164
                    goto jmp_insn;
1165
#if !defined(CONFIG_USER_ONLY)
1166
                case 0x39:        /* rett */
1167
                    {
1168
                        if (!supervisor(dc))
1169
                            goto priv_insn;
1170
                        gen_op_movl_npc_T0();
1171
                        gen_op_rett();
1172
                    }
1173
                    break;
1174
#endif
1175
                case 0x3b: /* flush */
1176
                    gen_op_flush_T0();
1177
                    break;
1178
                case 0x3c:        /* save */
1179
                    save_state(dc);
1180
                    gen_op_save();
1181
                    gen_movl_T0_reg(rd);
1182
                    break;
1183
                case 0x3d:        /* restore */
1184
                    save_state(dc);
1185
                    gen_op_restore();
1186
                    gen_movl_T0_reg(rd);
1187
                    break;
1188
                default:
1189
                    goto illegal_insn;
1190
                }
1191
            }
1192
            break;
1193
        }
1194
    case 3:                        /* load/store instructions */
1195
        {
1196
            unsigned int xop = GET_FIELD(insn, 7, 12);
1197
            rs1 = GET_FIELD(insn, 13, 17);
1198
            gen_movl_reg_T0(rs1);
1199
            if (IS_IMM) {        /* immediate */
1200
                rs2 = GET_FIELDs(insn, 19, 31);
1201
#if defined(OPTIM)
1202
                if (rs2 != 0) {
1203
#endif
1204
                    gen_movl_imm_T1(rs2);
1205
                    gen_op_add_T1_T0();
1206
#if defined(OPTIM)
1207
                }
1208
#endif
1209
            } else {                /* register */
1210
                rs2 = GET_FIELD(insn, 27, 31);
1211
#if defined(OPTIM)
1212
                if (rs2 != 0) {
1213
#endif
1214
                    gen_movl_reg_T1(rs2);
1215
                    gen_op_add_T1_T0();
1216
#if defined(OPTIM)
1217
                }
1218
#endif
1219
            }
1220
            if (xop < 4 || (xop > 7 && xop < 0x14) || \
1221
                    (xop > 0x17 && xop < 0x20)) {
1222
                switch (xop) {
1223
                case 0x0:        /* load word */
1224
                    gen_op_ldst(ld);
1225
                    break;
1226
                case 0x1:        /* load unsigned byte */
1227
                    gen_op_ldst(ldub);
1228
                    break;
1229
                case 0x2:        /* load unsigned halfword */
1230
                    gen_op_ldst(lduh);
1231
                    break;
1232
                case 0x3:        /* load double word */
1233
                    gen_op_ldst(ldd);
1234
                    gen_movl_T0_reg(rd + 1);
1235
                    break;
1236
                case 0x9:        /* load signed byte */
1237
                    gen_op_ldst(ldsb);
1238
                    break;
1239
                case 0xa:        /* load signed halfword */
1240
                    gen_op_ldst(ldsh);
1241
                    break;
1242
                case 0xd:        /* ldstub -- XXX: should be atomically */
1243
                    gen_op_ldst(ldstub);
1244
                    break;
1245
                case 0x0f:        /* swap register with memory. Also atomically */
1246
                    gen_movl_reg_T1(rd);
1247
                    gen_op_ldst(swap);
1248
                    break;
1249
#if !defined(CONFIG_USER_ONLY)
1250
                case 0x10:        /* load word alternate */
1251
                    if (!supervisor(dc))
1252
                        goto priv_insn;
1253
                    gen_op_lda(insn, 1, 4, 0);
1254
                    break;
1255
                case 0x11:        /* load unsigned byte alternate */
1256
                    if (!supervisor(dc))
1257
                        goto priv_insn;
1258
                    gen_op_lduba(insn, 1, 1, 0);
1259
                    break;
1260
                case 0x12:        /* load unsigned halfword alternate */
1261
                    if (!supervisor(dc))
1262
                        goto priv_insn;
1263
                    gen_op_lduha(insn, 1, 2, 0);
1264
                    break;
1265
                case 0x13:        /* load double word alternate */
1266
                    if (!supervisor(dc))
1267
                        goto priv_insn;
1268
                    gen_op_ldda(insn, 1, 8, 0);
1269
                    gen_movl_T0_reg(rd + 1);
1270
                    break;
1271
                case 0x19:        /* load signed byte alternate */
1272
                    if (!supervisor(dc))
1273
                        goto priv_insn;
1274
                    gen_op_ldsba(insn, 1, 1, 1);
1275
                    break;
1276
                case 0x1a:        /* load signed halfword alternate */
1277
                    if (!supervisor(dc))
1278
                        goto priv_insn;
1279
                    gen_op_ldsha(insn, 1, 2 ,1);
1280
                    break;
1281
                case 0x1d:        /* ldstuba -- XXX: should be atomically */
1282
                    if (!supervisor(dc))
1283
                        goto priv_insn;
1284
                    gen_op_ldstuba(insn, 1, 1, 0);
1285
                    break;
1286
                case 0x1f:        /* swap reg with alt. memory. Also atomically */
1287
                    if (!supervisor(dc))
1288
                        goto priv_insn;
1289
                    gen_movl_reg_T1(rd);
1290
                    gen_op_swapa(insn, 1, 4, 0);
1291
                    break;
1292
                    
1293
                    /* avoid warnings */
1294
                    (void) &gen_op_stfa;
1295
                    (void) &gen_op_stdfa;
1296
                    (void) &gen_op_ldfa;
1297
                    (void) &gen_op_lddfa;
1298
#endif
1299
                default:
1300
                    goto illegal_insn;
1301
                }
1302
                gen_movl_T1_reg(rd);
1303
            } else if (xop >= 0x20 && xop < 0x24) {
1304
#if !defined(CONFIG_USER_ONLY)
1305
                gen_op_trap_ifnofpu();
1306
#endif
1307
                switch (xop) {
1308
                case 0x20:        /* load fpreg */
1309
                    gen_op_ldst(ldf);
1310
                    gen_op_store_FT0_fpr(rd);
1311
                    break;
1312
                case 0x21:        /* load fsr */
1313
                    gen_op_ldfsr();
1314
                    gen_op_store_FT0_fpr(rd);
1315
                    break;
1316
                case 0x23:        /* load double fpreg */
1317
                    gen_op_ldst(lddf);
1318
                    gen_op_store_DT0_fpr(rd);
1319
                    break;
1320
                default:
1321
                    goto illegal_insn;
1322
                }
1323
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18)) {
1324
                gen_movl_reg_T1(rd);
1325
                switch (xop) {
1326
                case 0x4:
1327
                    gen_op_ldst(st);
1328
                    break;
1329
                case 0x5:
1330
                    gen_op_ldst(stb);
1331
                    break;
1332
                case 0x6:
1333
                    gen_op_ldst(sth);
1334
                    break;
1335
                case 0x7:
1336
                    flush_T2(dc);
1337
                    gen_movl_reg_T2(rd + 1);
1338
                    gen_op_ldst(std);
1339
                    break;
1340
#if !defined(CONFIG_USER_ONLY)
1341
                case 0x14:
1342
                    if (!supervisor(dc))
1343
                        goto priv_insn;
1344
                    gen_op_sta(insn, 0, 4, 0);
1345
                    break;
1346
                case 0x15:
1347
                    if (!supervisor(dc))
1348
                        goto priv_insn;
1349
                    gen_op_stba(insn, 0, 1, 0);
1350
                    break;
1351
                case 0x16:
1352
                    if (!supervisor(dc))
1353
                        goto priv_insn;
1354
                    gen_op_stha(insn, 0, 2, 0);
1355
                    break;
1356
                case 0x17:
1357
                    if (!supervisor(dc))
1358
                        goto priv_insn;
1359
                    flush_T2(dc);
1360
                    gen_movl_reg_T2(rd + 1);
1361
                    gen_op_stda(insn, 0, 8, 0);
1362
                    break;
1363
#endif
1364
                default:
1365
                    goto illegal_insn;
1366
                }
1367
            } else if (xop > 0x23 && xop < 0x28) {
1368
#if !defined(CONFIG_USER_ONLY)
1369
                gen_op_trap_ifnofpu();
1370
#endif
1371
                switch (xop) {
1372
                case 0x24:
1373
                    gen_op_load_fpr_FT0(rd);
1374
                    gen_op_ldst(stf);
1375
                    break;
1376
                case 0x25:
1377
                    gen_op_load_fpr_FT0(rd);
1378
                    gen_op_stfsr();
1379
                    break;
1380
                case 0x27:
1381
                    gen_op_load_fpr_DT0(rd);
1382
                    gen_op_ldst(stdf);
1383
                    break;
1384
                case 0x26: /* stdfq */
1385
                default:
1386
                    goto illegal_insn;
1387
                }
1388
            } else if (xop > 0x33 && xop < 0x38) {
1389
                /* Co-processor */
1390
                goto illegal_insn;
1391
            }
1392
            else
1393
                goto illegal_insn;
1394
        }
1395
    }
1396
    /* default case for non jump instructions */
1397
    if (dc->npc == DYNAMIC_PC) {
1398
        dc->pc = DYNAMIC_PC;
1399
        gen_op_next_insn();
1400
    } else if (dc->npc == JUMP_PC) {
1401
        /* we can do a static jump */
1402
        gen_op_branch2((long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
1403
        dc->is_br = 1;
1404
    } else {
1405
        dc->pc = dc->npc;
1406
        dc->npc = dc->npc + 4;
1407
    }
1408
 jmp_insn:
1409
    return;
1410
 illegal_insn:
1411
    save_state(dc);
1412
    gen_op_exception(TT_ILL_INSN);
1413
    dc->is_br = 1;
1414
    return;
1415
#if !defined(CONFIG_USER_ONLY)
1416
 priv_insn:
1417
    save_state(dc);
1418
    gen_op_exception(TT_PRIV_INSN);
1419
    dc->is_br = 1;
1420
    return;
1421
#endif
1422
 nfpu_insn:
1423
    save_state(dc);
1424
    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
1425
    dc->is_br = 1;
1426
}
1427

    
1428
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1429
                                                 int spc, CPUSPARCState *env)
1430
{
1431
    target_ulong pc_start, last_pc;
1432
    uint16_t *gen_opc_end;
1433
    DisasContext dc1, *dc = &dc1;
1434
    int j, lj = -1;
1435

    
1436
    memset(dc, 0, sizeof(DisasContext));
1437
    dc->tb = tb;
1438
    pc_start = tb->pc;
1439
    dc->pc = pc_start;
1440
    last_pc = dc->pc;
1441
    dc->npc = (target_ulong) tb->cs_base;
1442
#if defined(CONFIG_USER_ONLY)
1443
    dc->mem_idx = 0;
1444
#else
1445
    dc->mem_idx = ((env->psrs) != 0);
1446
#endif
1447
    gen_opc_ptr = gen_opc_buf;
1448
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1449
    gen_opparam_ptr = gen_opparam_buf;
1450

    
1451
    do {
1452
        if (env->nb_breakpoints > 0) {
1453
            for(j = 0; j < env->nb_breakpoints; j++) {
1454
                if (env->breakpoints[j] == dc->pc) {
1455
                    if (dc->pc != pc_start)
1456
                        save_state(dc);
1457
                    gen_op_debug();
1458
                    gen_op_movl_T0_0();
1459
                    gen_op_exit_tb();
1460
                    dc->is_br = 1;
1461
                    goto exit_gen_loop;
1462
                }
1463
            }
1464
        }
1465
        if (spc) {
1466
            if (loglevel > 0)
1467
                fprintf(logfile, "Search PC...\n");
1468
            j = gen_opc_ptr - gen_opc_buf;
1469
            if (lj < j) {
1470
                lj++;
1471
                while (lj < j)
1472
                    gen_opc_instr_start[lj++] = 0;
1473
                gen_opc_pc[lj] = dc->pc;
1474
                gen_opc_npc[lj] = dc->npc;
1475
                gen_opc_instr_start[lj] = 1;
1476
            }
1477
        }
1478
        last_pc = dc->pc;
1479
        disas_sparc_insn(dc);
1480
        if (dc->is_br)
1481
            break;
1482
        /* if the next PC is different, we abort now */
1483
        if (dc->pc != (last_pc + 4))
1484
            break;
1485
        /* if single step mode, we generate only one instruction and
1486
           generate an exception */
1487
        if (env->singlestep_enabled) {
1488
            gen_op_jmp_im(dc->pc);
1489
            gen_op_movl_T0_0();
1490
            gen_op_exit_tb();
1491
            break;
1492
        }
1493
    } while ((gen_opc_ptr < gen_opc_end) &&
1494
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1495

    
1496
 exit_gen_loop:
1497
    if (!dc->is_br) {
1498
        if (dc->pc != DYNAMIC_PC && 
1499
            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
1500
            /* static PC and NPC: we can use direct chaining */
1501
            gen_op_branch((long)tb, dc->pc, dc->npc);
1502
        } else {
1503
            if (dc->pc != DYNAMIC_PC)
1504
                gen_op_jmp_im(dc->pc);
1505
            save_npc(dc);
1506
            gen_op_movl_T0_0();
1507
            gen_op_exit_tb();
1508
        }
1509
    }
1510
    *gen_opc_ptr = INDEX_op_end;
1511
    if (spc) {
1512
        j = gen_opc_ptr - gen_opc_buf;
1513
        lj++;
1514
        while (lj <= j)
1515
            gen_opc_instr_start[lj++] = 0;
1516
        tb->size = 0;
1517
#if 0
1518
        if (loglevel > 0) {
1519
            page_dump(logfile);
1520
        }
1521
#endif
1522
    } else {
1523
        tb->size = last_pc + 4 - pc_start;
1524
    }
1525
#ifdef DEBUG_DISAS
1526
    if (loglevel & CPU_LOG_TB_IN_ASM) {
1527
        fprintf(logfile, "--------------\n");
1528
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1529
        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
1530
        fprintf(logfile, "\n");
1531
        if (loglevel & CPU_LOG_TB_OP) {
1532
            fprintf(logfile, "OP:\n");
1533
            dump_ops(gen_opc_buf, gen_opparam_buf);
1534
            fprintf(logfile, "\n");
1535
        }
1536
    }
1537
#endif
1538
    return 0;
1539
}
1540

    
1541
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
1542
{
1543
    return gen_intermediate_code_internal(tb, 0, env);
1544
}
1545

    
1546
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
1547
{
1548
    return gen_intermediate_code_internal(tb, 1, env);
1549
}
1550

    
1551
extern int ram_size;
1552

    
1553
void cpu_reset(CPUSPARCState *env)
1554
{
1555
    memset(env, 0, sizeof(*env));
1556
    env->cwp = 0;
1557
    env->wim = 1;
1558
    env->regwptr = env->regbase + (env->cwp * 16);
1559
#if defined(CONFIG_USER_ONLY)
1560
    env->user_mode_only = 1;
1561
#else
1562
    env->psrs = 1;
1563
    env->pc = 0xffd00000;
1564
    env->gregs[1] = ram_size;
1565
    env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
1566
    env->npc = env->pc + 4;
1567
#endif
1568
}
1569

    
1570
CPUSPARCState *cpu_sparc_init(void)
1571
{
1572
    CPUSPARCState *env;
1573

    
1574
    cpu_exec_init();
1575

    
1576
    if (!(env = malloc(sizeof(CPUSPARCState))))
1577
        return (NULL);
1578
    cpu_single_env = env;
1579
    cpu_reset(env);
1580
    return (env);
1581
}
1582

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

    
1585
void cpu_dump_state(CPUState *env, FILE *f, 
1586
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1587
                    int flags)
1588
{
1589
    int i, x;
1590

    
1591
    cpu_fprintf(f, "pc: 0x%08x  npc: 0x%08x\n", (int) env->pc, (int) env->npc);
1592
    cpu_fprintf(f, "General Registers:\n");
1593
    for (i = 0; i < 4; i++)
1594
        cpu_fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]);
1595
    cpu_fprintf(f, "\n");
1596
    for (; i < 8; i++)
1597
        cpu_fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]);
1598
    cpu_fprintf(f, "\nCurrent Register Window:\n");
1599
    for (x = 0; x < 3; x++) {
1600
        for (i = 0; i < 4; i++)
1601
            cpu_fprintf(f, "%%%c%d: 0x%08x\t",
1602
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1603
                    env->regwptr[i + x * 8]);
1604
        cpu_fprintf(f, "\n");
1605
        for (; i < 8; i++)
1606
            cpu_fprintf(f, "%%%c%d: 0x%08x\t",
1607
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1608
                    env->regwptr[i + x * 8]);
1609
        cpu_fprintf(f, "\n");
1610
    }
1611
    cpu_fprintf(f, "\nFloating Point Registers:\n");
1612
    for (i = 0; i < 32; i++) {
1613
        if ((i & 3) == 0)
1614
            cpu_fprintf(f, "%%f%02d:", i);
1615
        cpu_fprintf(f, " %016lf", env->fpr[i]);
1616
        if ((i & 3) == 3)
1617
            cpu_fprintf(f, "\n");
1618
    }
1619
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
1620
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1621
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1622
            env->psrs?'S':'-', env->psrps?'P':'-', 
1623
            env->psret?'E':'-', env->wim);
1624
    cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
1625
}
1626

    
1627
#if defined(CONFIG_USER_ONLY)
1628
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1629
{
1630
    return addr;
1631
}
1632

    
1633
#else
1634
extern int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
1635
                                 int *access_index, uint32_t address, int rw,
1636
                                 int is_user);
1637

    
1638
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1639
{
1640
    uint32_t phys_addr;
1641
    int prot, access_index;
1642

    
1643
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
1644
        return -1;
1645
    return phys_addr;
1646
}
1647
#endif
1648

    
1649
void helper_flush(target_ulong addr)
1650
{
1651
    addr &= ~7;
1652
    tb_invalidate_page_range(addr, addr + 8);
1653
}