Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ 7a3f1944

History | View | Annotate | Download (16.4 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
   There is also one big (currently unsolved) bug in the branch code:
38
   If a delay slot modifies the condition codes then the new condition
39
   codes, instead of the old ones will be used.
40

41
   TODO-list:
42

43
   FPU-Instructions
44
   Coprocessor-Instructions
45
   Fix above bug
46
   Check signedness issues
47
   Privileged instructions
48
   Register window overflow/underflow check
49
   Optimize synthetic instructions
50
   Optional alignment and privileged instruction check
51

52
   -- TMO, 09/03/03
53
 */
54

    
55
#include <stdarg.h>
56
#include <stdlib.h>
57
#include <stdio.h>
58
#include <string.h>
59
#include <inttypes.h>
60

    
61
#include "cpu.h"
62
#include "exec-all.h"
63
#include "disas.h"
64

    
65
#define DEBUG_DISAS
66

    
67
typedef struct DisasContext {
68
        uint8_t *pc;
69
        uint8_t *npc;
70
        void (*branch) (struct DisasContext *, uint32_t, uint32_t);
71
        unsigned int delay_slot:2;
72
        uint32_t insn;
73
        uint32_t target;
74
        int      is_br;
75
        struct TranslationBlock *tb;
76
} DisasContext;
77

    
78
static uint16_t *gen_opc_ptr;
79
static uint32_t *gen_opparam_ptr;
80
extern FILE *logfile;
81
extern int loglevel;
82

    
83
enum {
84
#define DEF(s,n,copy_size) INDEX_op_ ## s,
85
#include "opc.h"
86
#undef DEF
87
        NB_OPS
88
};
89

    
90
#include "gen-op.h"
91

    
92
#define GET_FIELD(X, FROM, TO) \
93
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
94

    
95
#define IS_IMM (insn & (1<<13))
96

    
97
static void disas_sparc_insn (DisasContext *dc);
98

    
99
typedef void (GenOpFunc)(void);
100
typedef void (GenOpFunc1)(long);
101
typedef void (GenOpFunc2)(long, long);
102
typedef void (GenOpFunc3)(long, long, long);
103

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

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

    
280
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
281
        gen_op_movl_T0_im,
282
        gen_op_movl_T1_im,
283
        gen_op_movl_T2_im
284
};
285

    
286
static inline void gen_movl_imm_TN (int reg, int imm)
287
{
288
        gen_op_movl_TN_im[reg](imm);
289
}
290

    
291
static inline void gen_movl_imm_T1 (int val)
292
{
293
        gen_movl_imm_TN (1, val);
294
}
295

    
296
static inline void gen_movl_imm_T0 (int val)
297
{
298
        gen_movl_imm_TN (0, val);
299
}
300

    
301
static inline void gen_movl_reg_TN (int reg, int t)
302
{
303
        if (reg) gen_op_movl_reg_TN[t][reg]();
304
        else gen_movl_imm_TN (t, 0);
305
}
306

    
307
static inline void gen_movl_reg_T0 (int reg)
308
{
309
        gen_movl_reg_TN (reg, 0);
310
}
311

    
312
static inline void gen_movl_reg_T1 (int reg)
313
{
314
        gen_movl_reg_TN (reg, 1);
315
}
316

    
317
static inline void gen_movl_reg_T2 (int reg)
318
{
319
        gen_movl_reg_TN (reg, 2);
320
}
321

    
322
static inline void gen_movl_TN_reg (int reg, int t)
323
{
324
        if (reg) gen_op_movl_TN_reg[t][reg]();
325
}
326

    
327
static inline void gen_movl_T0_reg (int reg)
328
{
329
        gen_movl_TN_reg (reg, 0);
330
}
331

    
332
static inline void gen_movl_T1_reg (int reg)
333
{
334
        gen_movl_TN_reg (reg, 1);
335
}
336

    
337
static void do_branch (DisasContext *dc, uint32_t target, uint32_t insn)
338
{
339
        unsigned int cond = GET_FIELD (insn, 3, 6), a = (insn & (1<<29)), ib = 0;
340
        target += (uint32_t) dc->pc-4;
341
        if (!a) disas_sparc_insn (dc);
342
        switch (cond) {
343
          case 0x0: gen_op_movl_T0_0 (); break;
344
          case 0x1: gen_op_eval_be (); break;
345
          case 0x2: gen_op_eval_ble (); break;
346
          case 0x3: gen_op_eval_bl (); break;
347
          case 0x4: gen_op_eval_bleu (); break;
348
          case 0x5: gen_op_eval_bcs (); break;
349
          case 0x6: gen_op_eval_bneg (); break;
350
          case 0x7: gen_op_eval_bvs (); break;
351
          case 0x8: gen_op_movl_T0_1 (); break;
352
          case 0x9: gen_op_eval_bne (); break;
353
          case 0xa: gen_op_eval_bg (); break;
354
          case 0xb: gen_op_eval_bge (); break;
355
          case 0xc: gen_op_eval_bgu (); break;
356
          case 0xd: gen_op_eval_bcc (); break;
357
          case 0xe: gen_op_eval_bpos (); break;
358
          case 0xf: gen_op_eval_bvc (); break;
359
        }
360
        if (a && ((cond|0x8) != 0x8)) {
361
                gen_op_generic_branch_a ((uint32_t) dc->tb,
362
                                (uint32_t) dc->pc+4, target);
363
                disas_sparc_insn (dc);
364
                ib = 1;
365
        }
366
        else
367
        if (cond && !a) {
368
                gen_op_generic_branch ((uint32_t) dc->tb, (uint32_t) target,
369
                        (uint32_t) dc->pc);
370
                ib = 1;
371
        }
372
        if (ib) dc->is_br = DISAS_JUMP;
373
}
374

    
375
/* target == 0x1 means CALL- else JMPL-instruction */
376
static void do_jump (DisasContext *dc, uint32_t target, uint32_t rd)
377
{
378
        uint32_t orig_pc = (uint32_t) dc->pc-8;
379
        if (target != 0x1)
380
         gen_op_generic_jmp_1 (orig_pc, target);
381
        else
382
         gen_op_generic_jmp_2 (orig_pc);
383
        gen_movl_T1_reg (rd);
384
        dc->is_br = DISAS_JUMP;
385
        gen_op_movl_T0_0 ();
386
}
387

    
388
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), b-a)
389

    
390
static int
391
sign_extend (x, len)
392
        int x, len;
393
{
394
        int signbit = (1 << (len - 1));
395
        int mask = (signbit << 1) - 1;
396
        return ((x & mask) ^ signbit) - signbit;
397
}
398

    
399
static void disas_sparc_insn (DisasContext *dc)
400
{
401
        unsigned int insn, opc, rs1, rs2, rd;
402

    
403
        if (dc->delay_slot == 1) {
404
                insn = dc->insn;
405
        } else {
406
                if (dc->delay_slot) dc->delay_slot--;
407
                insn = htonl (*(unsigned int *) (dc->pc));
408
                dc->pc += 4;
409
        }
410

    
411
        opc = GET_FIELD (insn, 0, 1);
412

    
413
        rd  = GET_FIELD (insn, 2, 6);
414
        switch (opc) {
415
          case 0: /* branches/sethi */
416
                {
417
                        unsigned int xop = GET_FIELD (insn, 7, 9);
418
                        int target;
419
                        target = GET_FIELD (insn, 10, 31);
420
                        switch (xop) {
421
                         case 0x0: case 0x1: /* UNIMPL */
422
                                printf ("UNIMPLEMENTED: %p\n", dc->pc-4);
423
                                exit (23);
424
                                break;
425
                         case 0x2: /* BN+x */
426
                        {
427
                                target <<= 2;
428
                                target = sign_extend (target, 22);
429
                                do_branch (dc, target, insn);
430
                                break;
431
                        }
432
                         case 0x3: /* FBN+x */
433
                                break;
434
                         case 0x4: /* SETHI */
435
                                gen_movl_imm_T0 (target<<10);
436
                                gen_movl_T0_reg (rd);
437
                                break;
438
                         case 0x5: /*CBN+x*/
439
                                break;
440
                        }
441
                        break;
442
                }
443
          case 1: /*CALL*/
444
                {
445
                        unsigned int target = GET_FIELDs (insn, 2, 31) << 2;
446
                        if (dc->delay_slot) {
447
                                do_jump (dc, target, 15);
448
                                dc->delay_slot = 0;
449
                        } else {
450
                                dc->insn = insn;
451
                                dc->delay_slot = 2;
452
                        }
453
                        break;
454
                }
455
          case 2: /* FPU & Logical Operations */
456
                {
457
                        unsigned int xop = GET_FIELD (insn, 7, 12);
458
                        if (xop == 58) { /* generate trap */
459
                                dc->is_br = DISAS_JUMP;
460
                                gen_op_jmp_im ((uint32_t) dc->pc);
461
                                if (IS_IMM) gen_op_trap (GET_FIELD (insn, 25, 31));
462
                                /* else XXX*/
463
                                gen_op_movl_T0_0 ();
464
                                break;
465
                        }
466
                        if (xop == 0x34 || xop == 0x35) { /* FPU Operations */
467
                                exit (33);
468
                        }
469
                        rs1 = GET_FIELD (insn, 13, 17);
470
                        gen_movl_reg_T0 (rs1);
471
                        if (IS_IMM) { /* immediate */
472
                                rs2 = GET_FIELDs (insn, 20, 31);
473
                                gen_movl_imm_T1 (rs2);
474
                        } else {              /* register */
475
                                rs2 = GET_FIELD (insn, 27, 31);
476
                                gen_movl_reg_T1 (rs2);
477
                        }
478
                        if (xop < 0x20) {
479
                         switch (xop &~ 0x10) {
480
                          case 0x0:
481
                                gen_op_add_T1_T0 ();
482
                                break;
483
                          case 0x1:
484
                                gen_op_and_T1_T0 ();
485
                                break;
486
                          case 0x2:
487
                                gen_op_or_T1_T0 ();
488
                                break;
489
                          case 0x3:
490
                                gen_op_xor_T1_T0 ();
491
                                break;
492
                          case 0x4:
493
                                gen_op_sub_T1_T0 ();
494
                                break;
495
                          case 0x5:
496
                                gen_op_andn_T1_T0 ();
497
                                break;
498
                          case 0x6:
499
                                gen_op_orn_T1_T0 ();
500
                                break;
501
                          case 0x7:
502
                                gen_op_xnor_T1_T0 ();
503
                                break;
504
                          case 0x8:
505
                                gen_op_addx_T1_T0 ();
506
                                break;
507
                          case 0xa:
508
                                gen_op_umul_T1_T0 ();
509
                                break;
510
                          case 0xb:
511
                                gen_op_smul_T1_T0 ();
512
                                break;
513
                          case 0xc:
514
                                gen_op_subx_T1_T0 ();
515
                                break;
516
                          case 0xe:
517
                                gen_op_udiv_T1_T0 ();
518
                                break;
519
                          case 0xf:
520
                                gen_op_sdiv_T1_T0 ();
521
                                break;
522
                          default:
523
                                exit (17);
524
                                break;
525
                         }
526
                         gen_movl_T0_reg (rd);
527
                         if (xop & 0x10) {
528
                                gen_op_set_flags ();
529
                         }
530
                        } else {
531
                          switch (xop) {
532
                                case 0x25: /* SLL */
533
                                        gen_op_sll ();
534
                                        break;
535
                                case 0x26:
536
                                        gen_op_srl ();
537
                                        break;
538
                                case 0x27:
539
                                        gen_op_sra ();
540
                                        break;
541
                                case 0x28: case 0x30:
542
                                {
543
                                        unsigned int rdi = GET_FIELD (insn, 13, 17);
544
                                        if (!rdi) (xop==0x28?gen_op_rdy ():gen_op_wry());
545
                                        /* else gen_op_su_trap (); */
546
                                        break;
547
                                }
548
                                /* Problem with jmpl: if restore is executed in the delay
549
                                   slot, then the wrong registers are beeing used */
550
                                case 0x38: /* jmpl */
551
                                {
552
                                        if (dc->delay_slot) {
553
                                                gen_op_add_T1_T0 ();
554
                                                do_jump (dc, 1, rd);
555
                                                dc->delay_slot = 0;
556
                                        } else {
557
                                                gen_op_add_T1_T0 ();
558
                                                gen_op_jmpl ();
559
                                                dc->insn = insn;
560
                                                dc->delay_slot = 2;
561
                                        }
562
                                        break;
563
                                }
564
                                case 0x3c: /* save */
565
                                        gen_op_add_T1_T0 ();
566
                                        gen_op_save ();
567
                                        gen_movl_T0_reg (rd);
568
                                        break;
569
                                case 0x3d: /* restore */
570
                                        gen_op_add_T1_T0 ();
571
                                        gen_op_restore ();
572
                                        gen_movl_T0_reg (rd);
573
                                        break;
574
                          }
575
                        }
576
                        break;
577
                }
578
          case 3: /* load/store instructions */
579
                {
580
                        unsigned int xop = GET_FIELD (insn, 7, 12);
581
                        rs1 = GET_FIELD (insn, 13, 17);
582
                        gen_movl_reg_T0 (rs1);
583
                        if (IS_IMM) { /* immediate */
584
                                rs2 = GET_FIELDs (insn, 20, 31);
585
                                gen_movl_imm_T1 (rs2);
586
                        } else {              /* register */
587
                                rs2 = GET_FIELD (insn, 27, 31);
588
                                gen_movl_reg_T1 (rs2);
589
                        }
590
                        gen_op_add_T1_T0 ();
591
                        if (xop < 4 || xop > 7)  {
592
                         switch (xop) {
593
                          case 0x0: /* load word */
594
                                gen_op_ld ();
595
                                break;
596
                          case 0x1: /* load unsigned byte */
597
                                gen_op_ldub ();
598
                                break;
599
                          case 0x2: /* load unsigned halfword */
600
                                gen_op_lduh ();
601
                                break;
602
                          case 0x3: /* load double word */
603
                                gen_op_ldd ();
604
                                gen_movl_T0_reg (rd+1);
605
                                break;
606
                          case 0x9: /* load signed byte */
607
                                gen_op_ldsb ();
608
                                break;
609
                          case 0xa: /* load signed halfword */
610
                                gen_op_ldsh ();
611
                                break;
612
                          case 0xd: /* ldstub -- XXX: should be atomically */
613
                                gen_op_ldstub ();
614
                                break;
615
                          case 0x0f: /* swap register with memory. Also atomically */
616
                                gen_op_swap ();
617
                                break;
618
                         }
619
                         gen_movl_T1_reg (rd);
620
                        } else if (xop < 8) {
621
                         gen_movl_reg_T1 (rd);
622
                         switch (xop) {
623
                          case 0x4:
624
                                gen_op_st ();
625
                                break;
626
                          case 0x5:
627
                                gen_op_stb ();
628
                                break;
629
                          case 0x6:
630
                                gen_op_sth ();
631
                                break;
632
                          case 0x7:
633
                                gen_op_st ();
634
                                gen_movl_reg_T1 (rd+1);
635
                                gen_op_st ();
636
                                break;
637
                         }
638
                        }
639
                }
640
        }
641
}
642

    
643
static inline int gen_intermediate_code_internal (TranslationBlock *tb, int spc)
644
{
645
        uint8_t *pc_start = (uint8_t *) tb->pc;
646
        uint16_t *gen_opc_end;
647
        DisasContext dc;
648

    
649
        memset (&dc, 0, sizeof (dc));
650
        if (spc) {
651
                printf ("SearchPC not yet supported\n");
652
                exit (0);
653
        }
654
        dc.tb = tb;
655
        dc.pc = pc_start;
656

    
657
        gen_opc_ptr = gen_opc_buf;
658
        gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
659
        gen_opparam_ptr = gen_opparam_buf;
660

    
661
        do {
662
                disas_sparc_insn (&dc);
663
        } while (!dc.is_br && (gen_opc_ptr < gen_opc_end) &&
664
                (dc.pc - pc_start) < (TARGET_PAGE_SIZE - 32));
665

    
666
        switch (dc.is_br) {
667
          case DISAS_JUMP:
668
          case DISAS_TB_JUMP:
669
                gen_op_exit_tb ();
670
                break;
671
        }
672

    
673
        *gen_opc_ptr = INDEX_op_end;
674
#ifdef DEBUG_DISAS
675
        if (loglevel) {
676
                fprintf (logfile, "--------------\n");
677
                fprintf (logfile, "IN: %s\n", lookup_symbol (pc_start));
678
                disas(logfile, pc_start, dc.pc - pc_start, 0, 0);
679
                fprintf(logfile, "\n");
680
                fprintf(logfile, "OP:\n");
681
                dump_ops(gen_opc_buf, gen_opparam_buf);
682
                fprintf(logfile, "\n");
683
        }
684
#endif
685

    
686
        return 0;
687
}
688

    
689
int gen_intermediate_code (CPUSPARCState *env, TranslationBlock *tb)
690
{
691
        return gen_intermediate_code_internal(tb, 0);
692
}
693

    
694
int gen_intermediate_code_pc (CPUSPARCState *env, TranslationBlock *tb)
695
{
696
        return gen_intermediate_code_internal(tb, 1);
697
}
698

    
699
void *mycpu;
700

    
701
CPUSPARCState *cpu_sparc_init (void)
702
{
703
        CPUSPARCState *env;
704

    
705
        cpu_exec_init ();
706

    
707
        if (!(env = malloc (sizeof(CPUSPARCState))))
708
                return (NULL);
709
        memset (env, 0, sizeof (*env));
710
        if (!(env->regwptr = malloc (0x2000)))
711
                return (NULL);
712
        memset (env->regwptr, 0, 0x2000);
713
        env->regwptr += 127;
714
        env->user_mode_only = 1;
715
        mycpu = env;
716
        return (env);
717
}
718

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

    
721
void cpu_sparc_dump_state (CPUSPARCState *env, FILE *f, int flags)
722
{
723
        int i, x;
724

    
725
        fprintf (f, "@PC: %p\n", (void *) env->pc);
726
        fprintf (f, "General Registers:\n");
727
        for (i=0;i<4;i++)
728
                fprintf (f, "%%g%c: %%%08x\t", i+'0', env->gregs[i]);
729
        fprintf (f, "\n");
730
        for (;i<8;i++)
731
                fprintf (f, "%%g%c: %%%08x\t", i+'0', env->gregs[i]);
732
        fprintf (f, "\nCurrent Register Window:\n");
733
        for (x=0;x<3;x++) {
734
          for (i=0;i<4;i++)
735
                fprintf (f, "%%%c%d: %%%08x\t", (x==0?'o':(x==1?'l':'i')), i, env->regwptr[i+x*8]);
736
          fprintf (f, "\n");
737
          for (;i<8;i++)
738
                fprintf (f, "%%%c%d: %%%08x\t", (x==0?'o':x==1?'l':'i'), i, env->regwptr[i+x*8]);
739
          fprintf (f, "\n");
740
        }
741
        fprintf (f, "PSR: %x -> %c%c%c%c\n", env->psr,
742
                        GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
743
                        GET_FLAG(PSR_NEG, 'N'),  GET_FLAG(PSR_CARRY, 'C'));
744
}