]> Git Repo - qemu.git/blob - target-sparc/translate.c
SPARC fixes: corrected PC/NPC logic (now slower but can be optimized a lot) - fixed...
[qemu.git] / target-sparc / translate.c
1 /*
2    SPARC translation
3
4    Copyright (C) 2003 Thomas M. Ogrisegg <[email protected]>
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 }
This page took 0.073686 seconds and 4 git commands to generate.