]> git.proxmox.com Git - 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 <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 }