Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ cf495bcf

History | View | Annotate | Download (22.1 kB)

1
/*
2
   SPARC translation
3

4
   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5

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

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

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

    
21
/*
22
   SPARC has two pitfalls: Delay slots and (a)nullification.
23
   This is currently solved as follows:
24

25
   'call' instructions simply execute the delay slot before the actual
26
   control transfer instructions.
27

28
   'jmpl' instructions execute calculate the destination, then execute
29
   the delay slot and then do the control transfer.
30

31
   (conditional) branch instructions are the most difficult ones, as the
32
   delay slot may be nullified (ie. not executed). This happens when a
33
   conditional branch is not executed (thus no control transfer happens)
34
   and the 'anull' bit in the branch instruction opcode is set. This is
35
   currently solved by doing a jump after the delay slot instruction.
36

37
   TODO-list:
38

39
   Register window overflow/underflow check
40
   FPU-Instructions
41
   Coprocessor-Instructions
42
   Check signedness issues
43
   Privileged instructions
44
   Optimize synthetic instructions
45
   Optional alignment and privileged instruction check
46

47
   -- TMO, 09/03/03
48
 */
49

    
50
#include <stdarg.h>
51
#include <stdlib.h>
52
#include <stdio.h>
53
#include <string.h>
54
#include <inttypes.h>
55

    
56
#include "cpu.h"
57
#include "exec-all.h"
58
#include "disas.h"
59

    
60
#define DEBUG_DISAS
61

    
62
typedef struct DisasContext {
63
    uint8_t *pc;                /* NULL means dynamic value */
64
    uint8_t *npc;                /* NULL means dynamic value */
65
    int is_br;
66
    struct TranslationBlock *tb;
67
} DisasContext;
68

    
69
static uint16_t *gen_opc_ptr;
70
static uint32_t *gen_opparam_ptr;
71
extern FILE *logfile;
72
extern int loglevel;
73

    
74
enum {
75
#define DEF(s,n,copy_size) INDEX_op_ ## s,
76
#include "opc.h"
77
#undef DEF
78
    NB_OPS
79
};
80

    
81
#include "gen-op.h"
82

    
83
#define GET_FIELD(X, FROM, TO) \
84
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
85

    
86
#define IS_IMM (insn & (1<<13))
87

    
88
static void disas_sparc_insn(DisasContext * dc);
89

    
90
typedef void (GenOpFunc) (void);
91
typedef void (GenOpFunc1) (long);
92
typedef void (GenOpFunc2) (long, long);
93
typedef void (GenOpFunc3) (long, long, long);
94

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

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

    
271
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
272
    gen_op_movl_T0_im,
273
    gen_op_movl_T1_im,
274
    gen_op_movl_T2_im
275
};
276

    
277
static inline void gen_movl_imm_TN(int reg, int imm)
278
{
279
    gen_op_movl_TN_im[reg] (imm);
280
}
281

    
282
static inline void gen_movl_imm_T1(int val)
283
{
284
    gen_movl_imm_TN(1, val);
285
}
286

    
287
static inline void gen_movl_imm_T0(int val)
288
{
289
    gen_movl_imm_TN(0, val);
290
}
291

    
292
static inline void gen_movl_reg_TN(int reg, int t)
293
{
294
    if (reg)
295
        gen_op_movl_reg_TN[t][reg] ();
296
    else
297
        gen_movl_imm_TN(t, 0);
298
}
299

    
300
static inline void gen_movl_reg_T0(int reg)
301
{
302
    gen_movl_reg_TN(reg, 0);
303
}
304

    
305
static inline void gen_movl_reg_T1(int reg)
306
{
307
    gen_movl_reg_TN(reg, 1);
308
}
309

    
310
static inline void gen_movl_reg_T2(int reg)
311
{
312
    gen_movl_reg_TN(reg, 2);
313
}
314

    
315
static inline void gen_movl_TN_reg(int reg, int t)
316
{
317
    if (reg)
318
        gen_op_movl_TN_reg[t][reg] ();
319
}
320

    
321
static inline void gen_movl_T0_reg(int reg)
322
{
323
    gen_movl_TN_reg(reg, 0);
324
}
325

    
326
static inline void gen_movl_T1_reg(int reg)
327
{
328
    gen_movl_TN_reg(reg, 1);
329
}
330

    
331
static void gen_cond(int cond)
332
{
333
        switch (cond) {
334
        case 0x0:
335
            gen_op_movl_T2_0();
336
            break;
337
        case 0x1:
338
            gen_op_eval_be();
339
            break;
340
        case 0x2:
341
            gen_op_eval_ble();
342
            break;
343
        case 0x3:
344
            gen_op_eval_bl();
345
            break;
346
        case 0x4:
347
            gen_op_eval_bleu();
348
            break;
349
        case 0x5:
350
            gen_op_eval_bcs();
351
            break;
352
        case 0x6:
353
            gen_op_eval_bneg();
354
            break;
355
        case 0x7:
356
            gen_op_eval_bvs();
357
            break;
358
        case 0x8:
359
            gen_op_movl_T2_1();
360
            break;
361
        case 0x9:
362
            gen_op_eval_bne();
363
            break;
364
        case 0xa:
365
            gen_op_eval_bg();
366
            break;
367
        case 0xb:
368
            gen_op_eval_bge();
369
            break;
370
        case 0xc:
371
            gen_op_eval_bgu();
372
            break;
373
        case 0xd:
374
            gen_op_eval_bcc();
375
            break;
376
        case 0xe:
377
            gen_op_eval_bpos();
378
            break;
379
        default:
380
        case 0xf:
381
            gen_op_eval_bvc();
382
            break;
383
        }
384
}
385

    
386

    
387
static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
388
{
389
    unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
390
    target += (uint32_t) dc->pc;
391
    if (cond == 0x0) {
392
        /* unconditional not taken */
393
        if (a) {
394
            dc->pc = dc->npc + 4;
395
            dc->npc = dc->pc + 4;
396
        } else {
397
            dc->pc = dc->npc;
398
            dc->npc = dc->pc + 4;
399
        }
400
    } else if (cond == 0x8) {
401
        /* unconditional taken */
402
        if (a) {
403
            dc->pc = (uint8_t *) target;
404
            dc->npc = dc->pc + 4;
405
        } else {
406
            dc->pc = dc->npc;
407
            dc->npc = (uint8_t *) target;
408
        }
409
    } else {
410
        gen_cond(cond);
411
        if (a) {
412
            gen_op_generic_branch_a((uint32_t) target,
413
                                    (uint32_t) (dc->npc));
414
            dc->is_br = 1;
415
            dc->pc = NULL;
416
            dc->npc = NULL;
417
        } else {
418
            dc->pc = dc->npc;
419
            gen_op_generic_branch((uint32_t) target,
420
                                  (uint32_t) (dc->npc + 4));
421
            dc->npc = NULL;
422
        }
423
    }
424
}
425

    
426
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
427

    
428
static int sign_extend(int x, int len)
429
{
430
    len = 32 - len;
431
    return (x << len) >> len;
432
}
433

    
434
static inline void save_state(DisasContext * dc)
435
{
436
    gen_op_jmp_im((uint32_t)dc->pc);
437
    if (dc->npc != NULL)
438
        gen_op_movl_npc_im((long) dc->npc);
439
}
440

    
441
static void disas_sparc_insn(DisasContext * dc)
442
{
443
    unsigned int insn, opc, rs1, rs2, rd;
444

    
445
    insn = ldl_code(dc->pc);
446
    opc = GET_FIELD(insn, 0, 1);
447

    
448
    rd = GET_FIELD(insn, 2, 6);
449
    switch (opc) {
450
    case 0:                        /* branches/sethi */
451
        {
452
            unsigned int xop = GET_FIELD(insn, 7, 9);
453
            int target;
454
            target = GET_FIELD(insn, 10, 31);
455
            switch (xop) {
456
            case 0x0:
457
            case 0x1:                /* UNIMPL */
458
                goto illegal_insn;
459
            case 0x2:                /* BN+x */
460
                {
461
                    target <<= 2;
462
                    target = sign_extend(target, 22);
463
                    do_branch(dc, target, insn);
464
                    goto jmp_insn;
465
                }
466
            case 0x3:                /* FBN+x */
467
                break;
468
            case 0x4:                /* SETHI */
469
                gen_movl_imm_T0(target << 10);
470
                gen_movl_T0_reg(rd);
471
                break;
472
            case 0x5:                /*CBN+x */
473
                break;
474
            }
475
            break;
476
        }
477
    case 1:
478
        /*CALL*/ {
479
            unsigned int target = GET_FIELDs(insn, 2, 31) << 2;
480

    
481
            gen_op_movl_T0_im((long) (dc->pc));
482
            gen_movl_T0_reg(15);
483
            target = (long) dc->pc + target;
484
            dc->pc = dc->npc;
485
            dc->npc = (uint8_t *) target;
486
        }
487
        goto jmp_insn;
488
    case 2:                        /* FPU & Logical Operations */
489
        {
490
            unsigned int xop = GET_FIELD(insn, 7, 12);
491
            if (xop == 0x3a) {        /* generate trap */
492
                int cond;
493
                rs1 = GET_FIELD(insn, 13, 17);
494
                gen_movl_reg_T0(rs1);
495
                if (IS_IMM) {
496
                    gen_movl_imm_T1(GET_FIELD(insn, 25, 31));
497
                } else {
498
                    rs2 = GET_FIELD(insn, 27, 31);
499
                    gen_movl_reg_T1(rs2);
500
                }
501
                gen_op_add_T1_T0();
502
                save_state(dc);
503
                cond = GET_FIELD(insn, 3, 6);
504
                if (cond == 0x8) {
505
                    gen_op_trap_T0();
506
                    dc->is_br = 1;
507
                    goto jmp_insn;
508
                } else {
509
                    gen_op_trapcc_T0();
510
                }
511
            } else if (xop == 0x28) {
512
                rs1 = GET_FIELD(insn, 13, 17);
513
                switch(rs1) {
514
                case 0: /* rdy */
515
                    gen_op_rdy();
516
                    gen_movl_T0_reg(rd);
517
                    break;
518
                default:
519
                    goto illegal_insn;
520
                }
521
            } else if (xop == 0x34 || xop == 0x35) {        /* FPU Operations */
522
                goto illegal_insn;
523
            } else {
524
                rs1 = GET_FIELD(insn, 13, 17);
525
                gen_movl_reg_T0(rs1);
526
                if (IS_IMM) {        /* immediate */
527
                    rs2 = GET_FIELDs(insn, 19, 31);
528
                    gen_movl_imm_T1(rs2);
529
                } else {                /* register */
530
                    rs2 = GET_FIELD(insn, 27, 31);
531
                    gen_movl_reg_T1(rs2);
532
                }
533
                if (xop < 0x20) {
534
                    switch (xop & ~0x10) {
535
                    case 0x0:
536
                        if (xop & 0x10)
537
                            gen_op_add_T1_T0_cc();
538
                        else
539
                            gen_op_add_T1_T0();
540
                        break;
541
                    case 0x1:
542
                        gen_op_and_T1_T0();
543
                        if (xop & 0x10)
544
                            gen_op_logic_T0_cc();
545
                        break;
546
                    case 0x2:
547
                        gen_op_or_T1_T0();
548
                        if (xop & 0x10)
549
                            gen_op_logic_T0_cc();
550
                        break;
551
                    case 0x3:
552
                        gen_op_xor_T1_T0();
553
                        if (xop & 0x10)
554
                            gen_op_logic_T0_cc();
555
                        break;
556
                    case 0x4:
557
                        if (xop & 0x10)
558
                            gen_op_sub_T1_T0_cc();
559
                        else
560
                            gen_op_sub_T1_T0();
561
                        break;
562
                    case 0x5:
563
                        gen_op_andn_T1_T0();
564
                        if (xop & 0x10)
565
                            gen_op_logic_T0_cc();
566
                        break;
567
                    case 0x6:
568
                        gen_op_orn_T1_T0();
569
                        if (xop & 0x10)
570
                            gen_op_logic_T0_cc();
571
                        break;
572
                    case 0x7:
573
                        gen_op_xnor_T1_T0();
574
                        if (xop & 0x10)
575
                            gen_op_logic_T0_cc();
576
                        break;
577
                    case 0x8:
578
                        gen_op_addx_T1_T0();
579
                        if (xop & 0x10)
580
                            gen_op_set_flags();
581
                        break;
582
                    case 0xa:
583
                        gen_op_umul_T1_T0();
584
                        if (xop & 0x10)
585
                            gen_op_logic_T0_cc();
586
                        break;
587
                    case 0xb:
588
                        gen_op_smul_T1_T0();
589
                        if (xop & 0x10)
590
                            gen_op_logic_T0_cc();
591
                        break;
592
                    case 0xc:
593
                        gen_op_subx_T1_T0();
594
                        if (xop & 0x10)
595
                            gen_op_set_flags();
596
                        break;
597
                    case 0xe:
598
                        gen_op_udiv_T1_T0();
599
                        if (xop & 0x10)
600
                            gen_op_div_cc();
601
                        break;
602
                    case 0xf:
603
                        gen_op_sdiv_T1_T0();
604
                        if (xop & 0x10)
605
                            gen_op_div_cc();
606
                        break;
607
                    default:
608
                        goto illegal_insn;
609
                    }
610
                    gen_movl_T0_reg(rd);
611
                } else {
612
                    switch (xop) {
613
                    case 0x24: /* mulscc */
614
                        gen_op_mulscc_T1_T0();
615
                        gen_movl_T0_reg(rd);
616
                        break;
617
                    case 0x25:        /* SLL */
618
                        gen_op_sll();
619
                        gen_movl_T0_reg(rd);
620
                        break;
621
                    case 0x26:
622
                        gen_op_srl();
623
                        gen_movl_T0_reg(rd);
624
                        break;
625
                    case 0x27:
626
                        gen_op_sra();
627
                        gen_movl_T0_reg(rd);
628
                        break;
629
                    case 0x30:
630
                        {
631
                            gen_op_xor_T1_T0();
632
                            switch(rd) {
633
                            case 0:
634
                                gen_op_wry();
635
                                break;
636
                            default:
637
                                goto illegal_insn;
638
                            }
639
                        }
640
                        break;
641
                    case 0x38:        /* jmpl */
642
                        {
643
                            gen_op_add_T1_T0();
644
                            gen_op_movl_npc_T0();
645
                            if (rd != 0) {
646
                                gen_op_movl_T0_im((long) (dc->pc));
647
                                gen_movl_T0_reg(rd);
648
                            }
649
                            dc->pc = dc->npc;
650
                            dc->npc = NULL;
651
                        }
652
                        goto jmp_insn;
653
                    case 0x3b: /* flush */
654
                        /* nothing to do */
655
                        break;
656
                    case 0x3c:        /* save */
657
                        save_state(dc);
658
                        gen_op_add_T1_T0();
659
                        gen_op_save();
660
                        gen_movl_T0_reg(rd);
661
                        break;
662
                    case 0x3d:        /* restore */
663
                        save_state(dc);
664
                        gen_op_add_T1_T0();
665
                        gen_op_restore();
666
                        gen_movl_T0_reg(rd);
667
                        break;
668
                    default:
669
                        goto illegal_insn;
670
                    }
671
                }
672
            }
673
            break;
674
        }
675
    case 3:                        /* load/store instructions */
676
        {
677
            unsigned int xop = GET_FIELD(insn, 7, 12);
678
            rs1 = GET_FIELD(insn, 13, 17);
679
            gen_movl_reg_T0(rs1);
680
            if (IS_IMM) {        /* immediate */
681
                rs2 = GET_FIELDs(insn, 19, 31);
682
                gen_movl_imm_T1(rs2);
683
            } else {                /* register */
684
                rs2 = GET_FIELD(insn, 27, 31);
685
                gen_movl_reg_T1(rs2);
686
            }
687
            gen_op_add_T1_T0();
688
            if (xop < 4 || xop > 7) {
689
                switch (xop) {
690
                case 0x0:        /* load word */
691
                    gen_op_ld();
692
                    break;
693
                case 0x1:        /* load unsigned byte */
694
                    gen_op_ldub();
695
                    break;
696
                case 0x2:        /* load unsigned halfword */
697
                    gen_op_lduh();
698
                    break;
699
                case 0x3:        /* load double word */
700
                    gen_op_ldd();
701
                    gen_movl_T0_reg(rd + 1);
702
                    break;
703
                case 0x9:        /* load signed byte */
704
                    gen_op_ldsb();
705
                    break;
706
                case 0xa:        /* load signed halfword */
707
                    gen_op_ldsh();
708
                    break;
709
                case 0xd:        /* ldstub -- XXX: should be atomically */
710
                    gen_op_ldstub();
711
                    break;
712
                case 0x0f:        /* swap register with memory. Also atomically */
713
                    gen_op_swap();
714
                    break;
715
                }
716
                gen_movl_T1_reg(rd);
717
            } else if (xop < 8) {
718
                gen_movl_reg_T1(rd);
719
                switch (xop) {
720
                case 0x4:
721
                    gen_op_st();
722
                    break;
723
                case 0x5:
724
                    gen_op_stb();
725
                    break;
726
                case 0x6:
727
                    gen_op_sth();
728
                    break;
729
                case 0x7:
730
                    gen_movl_reg_T2(rd + 1);
731
                    gen_op_std();
732
                    break;
733
                }
734
            }
735
        }
736
    }
737
    /* default case for non jump instructions */
738
    if (dc->npc != NULL) {
739
        dc->pc = dc->npc;
740
        dc->npc = dc->npc + 4;
741
    } else {
742
        dc->pc = NULL;
743
        gen_op_next_insn();
744
    }
745
  jmp_insn:;
746
    return;
747
 illegal_insn:
748
    gen_op_jmp_im((uint32_t)dc->pc);
749
    if (dc->npc != NULL)
750
        gen_op_movl_npc_im((long) dc->npc);
751
    gen_op_exception(TT_ILL_INSN);
752
    dc->is_br = 1;
753
}
754

    
755
static inline int gen_intermediate_code_internal(TranslationBlock * tb,
756
                                                 int spc)
757
{
758
    uint8_t *pc_start, *last_pc;
759
    uint16_t *gen_opc_end;
760
    DisasContext dc1, *dc = &dc1;
761

    
762
    memset(dc, 0, sizeof(DisasContext));
763
    if (spc) {
764
        printf("SearchPC not yet supported\n");
765
        exit(0);
766
    }
767
    dc->tb = tb;
768
    pc_start = (uint8_t *) tb->pc;
769
    dc->pc = pc_start;
770
    dc->npc = (uint8_t *) tb->cs_base;
771

    
772
    gen_opc_ptr = gen_opc_buf;
773
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
774
    gen_opparam_ptr = gen_opparam_buf;
775

    
776
    do {
777
        last_pc = dc->pc;
778
        disas_sparc_insn(dc);
779
        if (dc->is_br)
780
            break;
781
        /* if the next PC is different, we abort now */
782
        if (dc->pc != (last_pc + 4))
783
            break;
784
    } while ((gen_opc_ptr < gen_opc_end) &&
785
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
786
    if (dc->pc != NULL)
787
        gen_op_jmp_im((long) dc->pc);
788
    if (dc->npc != NULL)
789
        gen_op_movl_npc_im((long) dc->npc);
790
    gen_op_movl_T0_0();
791
    gen_op_exit_tb();
792

    
793
    *gen_opc_ptr = INDEX_op_end;
794
#ifdef DEBUG_DISAS
795
    if (loglevel) {
796
        fprintf(logfile, "--------------\n");
797
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
798
        disas(logfile, pc_start, last_pc + 4 - pc_start, 0, 0);
799
        fprintf(logfile, "\n");
800
        fprintf(logfile, "OP:\n");
801
        dump_ops(gen_opc_buf, gen_opparam_buf);
802
        fprintf(logfile, "\n");
803
    }
804
#endif
805

    
806
    return 0;
807
}
808

    
809
int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
810
{
811
    return gen_intermediate_code_internal(tb, 0);
812
}
813

    
814
int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
815
{
816
    return gen_intermediate_code_internal(tb, 1);
817
}
818

    
819
CPUSPARCState *cpu_sparc_init(void)
820
{
821
    CPUSPARCState *env;
822

    
823
    cpu_exec_init();
824

    
825
    if (!(env = malloc(sizeof(CPUSPARCState))))
826
        return (NULL);
827
    memset(env, 0, sizeof(*env));
828
    env->cwp = 0;
829
    env->wim = 1;
830
    env->regwptr = env->regbase + (env->cwp * 16);
831
    env->user_mode_only = 1;
832
    return (env);
833
}
834

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

    
837
void cpu_sparc_dump_state(CPUSPARCState * env, FILE * f, int flags)
838
{
839
    int i, x;
840

    
841
    fprintf(f, "pc: 0x%08x  npc: 0x%08x\n", (int) env->pc, (int) env->npc);
842
    fprintf(f, "General Registers:\n");
843
    for (i = 0; i < 4; i++)
844
        fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]);
845
    fprintf(f, "\n");
846
    for (; i < 8; i++)
847
        fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]);
848
    fprintf(f, "\nCurrent Register Window:\n");
849
    for (x = 0; x < 3; x++) {
850
        for (i = 0; i < 4; i++)
851
            fprintf(f, "%%%c%d: 0x%08x\t",
852
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
853
                    env->regwptr[i + x * 8]);
854
        fprintf(f, "\n");
855
        for (; i < 8; i++)
856
            fprintf(f, "%%%c%d: 0x%08x\t",
857
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
858
                    env->regwptr[i + x * 8]);
859
        fprintf(f, "\n");
860
    }
861
    fprintf(f, "psr: 0x%08x -> %c%c%c%c wim: 0x%08x\n", env->psr | env->cwp,
862
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
863
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
864
            env->wim);
865
}