Commit 72cbca10e184637ec0e813ead71975b7446cc695

Authored by bellard
1 parent 34f715e7

direct chaining support for SPARC


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@607 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/op.c
... ... @@ -643,24 +643,43 @@ void OPPROTO op_next_insn(void)
643 643 env->npc = env->npc + 4;
644 644 }
645 645  
646   -void OPPROTO op_generic_branch(void)
  646 +void OPPROTO op_branch(void)
  647 +{
  648 + env->npc = PARAM3; /* XXX: optimize */
  649 + JUMP_TB(op_branch, PARAM1, 0, PARAM2);
  650 +}
  651 +
  652 +void OPPROTO op_branch2(void)
647 653 {
648 654 if (T2) {
649   - env->npc = PARAM1;
  655 + env->npc = PARAM2 + 4;
  656 + JUMP_TB(op_branch2, PARAM1, 0, PARAM2);
650 657 } else {
651   - env->npc = PARAM2;
  658 + env->npc = PARAM3 + 4;
  659 + JUMP_TB(op_branch2, PARAM1, 1, PARAM3);
  660 + }
  661 + FORCE_RET();
  662 +}
  663 +
  664 +void OPPROTO op_branch_a(void)
  665 +{
  666 + if (T2) {
  667 + env->npc = PARAM2; /* XXX: optimize */
  668 + JUMP_TB(op_generic_branch_a, PARAM1, 0, PARAM3);
  669 + } else {
  670 + env->npc = PARAM3 + 8; /* XXX: optimize */
  671 + JUMP_TB(op_generic_branch_a, PARAM1, 1, PARAM3 + 4);
652 672 }
653 673 FORCE_RET();
654 674 }
655 675  
656   -void OPPROTO op_generic_branch_a(void)
  676 +void OPPROTO op_generic_branch(void)
657 677 {
658 678 if (T2) {
659   - env->pc = PARAM2;
660 679 env->npc = PARAM1;
661 680 } else {
662   - env->pc = PARAM2 + 4;
663   - env->npc = PARAM2 + 8;
  681 + env->npc = PARAM2;
664 682 }
665 683 FORCE_RET();
666 684 }
  685 +
... ...
target-sparc/translate.c
... ... @@ -42,9 +42,14 @@
42 42  
43 43 #define DEBUG_DISAS
44 44  
  45 +#define DYNAMIC_PC 1 /* dynamic pc value */
  46 +#define JUMP_PC 2 /* dynamic pc value which takes only two values
  47 + according to jump_pc[T2] */
  48 +
45 49 typedef struct DisasContext {
46   - uint8_t *pc; /* NULL means dynamic value */
47   - uint8_t *npc; /* NULL means dynamic value */
  50 + target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
  51 + target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
  52 + target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
48 53 int is_br;
49 54 struct TranslationBlock *tb;
50 55 } DisasContext;
... ... @@ -306,6 +311,31 @@ static inline void gen_movl_T1_reg(int reg)
306 311 gen_movl_TN_reg(reg, 1);
307 312 }
308 313  
  314 +/* call this function before using T2 as it may have been set for a jump */
  315 +static inline void flush_T2(DisasContext * dc)
  316 +{
  317 + if (dc->npc == JUMP_PC) {
  318 + gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
  319 + dc->npc = DYNAMIC_PC;
  320 + }
  321 +}
  322 +
  323 +static inline void save_npc(DisasContext * dc)
  324 +{
  325 + if (dc->npc == JUMP_PC) {
  326 + gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
  327 + dc->npc = DYNAMIC_PC;
  328 + } else if (dc->npc != DYNAMIC_PC) {
  329 + gen_op_movl_npc_im(dc->npc);
  330 + }
  331 +}
  332 +
  333 +static inline void save_state(DisasContext * dc)
  334 +{
  335 + gen_op_jmp_im((uint32_t)dc->pc);
  336 + save_npc(dc);
  337 +}
  338 +
309 339 static void gen_cond(int cond)
310 340 {
311 341 switch (cond) {
... ... @@ -378,25 +408,23 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
378 408 } else if (cond == 0x8) {
379 409 /* unconditional taken */
380 410 if (a) {
381   - dc->pc = (uint8_t *) target;
  411 + dc->pc = target;
382 412 dc->npc = dc->pc + 4;
383 413 } else {
384 414 dc->pc = dc->npc;
385   - dc->npc = (uint8_t *) target;
  415 + dc->npc = target;
386 416 }
387 417 } else {
  418 + flush_T2(dc);
388 419 gen_cond(cond);
389 420 if (a) {
390   - gen_op_generic_branch_a((uint32_t) target,
391   - (uint32_t) (dc->npc));
  421 + gen_op_branch_a((long)dc->tb, target, dc->npc);
392 422 dc->is_br = 1;
393   - dc->pc = NULL;
394   - dc->npc = NULL;
395 423 } else {
396 424 dc->pc = dc->npc;
397   - gen_op_generic_branch((uint32_t) target,
398   - (uint32_t) (dc->npc + 4));
399   - dc->npc = NULL;
  425 + dc->jump_pc[0] = target;
  426 + dc->jump_pc[1] = dc->npc + 4;
  427 + dc->npc = JUMP_PC;
400 428 }
401 429 }
402 430 }
... ... @@ -409,18 +437,11 @@ static int sign_extend(int x, int len)
409 437 return (x << len) >> len;
410 438 }
411 439  
412   -static inline void save_state(DisasContext * dc)
413   -{
414   - gen_op_jmp_im((uint32_t)dc->pc);
415   - if (dc->npc != NULL)
416   - gen_op_movl_npc_im((long) dc->npc);
417   -}
418   -
419 440 static void disas_sparc_insn(DisasContext * dc)
420 441 {
421 442 unsigned int insn, opc, rs1, rs2, rd;
422 443  
423   - insn = ldl_code(dc->pc);
  444 + insn = ldl_code((uint8_t *)dc->pc);
424 445 opc = GET_FIELD(insn, 0, 1);
425 446  
426 447 rd = GET_FIELD(insn, 2, 6);
... ... @@ -458,9 +479,9 @@ static void disas_sparc_insn(DisasContext * dc)
458 479  
459 480 gen_op_movl_T0_im((long) (dc->pc));
460 481 gen_movl_T0_reg(15);
461   - target = (long) dc->pc + target;
  482 + target = dc->pc + target;
462 483 dc->pc = dc->npc;
463   - dc->npc = (uint8_t *) target;
  484 + dc->npc = target;
464 485 }
465 486 goto jmp_insn;
466 487 case 2: /* FPU & Logical Operations */
... ... @@ -625,7 +646,7 @@ static void disas_sparc_insn(DisasContext * dc)
625 646 gen_movl_T0_reg(rd);
626 647 }
627 648 dc->pc = dc->npc;
628   - dc->npc = NULL;
  649 + dc->npc = DYNAMIC_PC;
629 650 }
630 651 goto jmp_insn;
631 652 case 0x3b: /* flush */
... ... @@ -705,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc)
705 726 gen_op_sth();
706 727 break;
707 728 case 0x7:
  729 + flush_T2(dc);
708 730 gen_movl_reg_T2(rd + 1);
709 731 gen_op_std();
710 732 break;
... ... @@ -713,19 +735,21 @@ static void disas_sparc_insn(DisasContext * dc)
713 735 }
714 736 }
715 737 /* default case for non jump instructions */
716   - if (dc->npc != NULL) {
  738 + if (dc->npc == DYNAMIC_PC) {
  739 + dc->pc = DYNAMIC_PC;
  740 + gen_op_next_insn();
  741 + } else if (dc->npc == JUMP_PC) {
  742 + /* we can do a static jump */
  743 + gen_op_branch2((long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
  744 + dc->is_br = 1;
  745 + } else {
717 746 dc->pc = dc->npc;
718 747 dc->npc = dc->npc + 4;
719   - } else {
720   - dc->pc = NULL;
721   - gen_op_next_insn();
722 748 }
723 749 jmp_insn:;
724 750 return;
725 751 illegal_insn:
726   - gen_op_jmp_im((uint32_t)dc->pc);
727   - if (dc->npc != NULL)
728   - gen_op_movl_npc_im((long) dc->npc);
  752 + save_state(dc);
729 753 gen_op_exception(TT_ILL_INSN);
730 754 dc->is_br = 1;
731 755 }
... ... @@ -733,7 +757,7 @@ static void disas_sparc_insn(DisasContext * dc)
733 757 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
734 758 int spc)
735 759 {
736   - uint8_t *pc_start, *last_pc;
  760 + target_ulong pc_start, last_pc;
737 761 uint16_t *gen_opc_end;
738 762 DisasContext dc1, *dc = &dc1;
739 763  
... ... @@ -743,9 +767,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
743 767 exit(0);
744 768 }
745 769 dc->tb = tb;
746   - pc_start = (uint8_t *) tb->pc;
  770 + pc_start = tb->pc;
747 771 dc->pc = pc_start;
748   - dc->npc = (uint8_t *) tb->cs_base;
  772 + dc->npc = (target_ulong) tb->cs_base;
749 773  
750 774 gen_opc_ptr = gen_opc_buf;
751 775 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
... ... @@ -761,19 +785,25 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
761 785 break;
762 786 } while ((gen_opc_ptr < gen_opc_end) &&
763 787 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
764   - if (dc->pc != NULL)
765   - gen_op_jmp_im((long) dc->pc);
766   - if (dc->npc != NULL)
767   - gen_op_movl_npc_im((long) dc->npc);
768   - gen_op_movl_T0_0();
769   - gen_op_exit_tb();
770   -
  788 + if (!dc->is_br) {
  789 + if (dc->pc != DYNAMIC_PC &&
  790 + (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
  791 + /* static PC and NPC: we can use direct chaining */
  792 + gen_op_branch((long)tb, dc->pc, dc->npc);
  793 + } else {
  794 + if (dc->pc != DYNAMIC_PC)
  795 + gen_op_jmp_im(dc->pc);
  796 + save_npc(dc);
  797 + gen_op_movl_T0_0();
  798 + gen_op_exit_tb();
  799 + }
  800 + }
771 801 *gen_opc_ptr = INDEX_op_end;
772 802 #ifdef DEBUG_DISAS
773 803 if (loglevel) {
774 804 fprintf(logfile, "--------------\n");
775   - fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
776   - disas(logfile, pc_start, last_pc + 4 - pc_start, 0, 0);
  805 + fprintf(logfile, "IN: %s\n", lookup_symbol((uint8_t *)pc_start));
  806 + disas(logfile, (uint8_t *)pc_start, last_pc + 4 - pc_start, 0, 0);
777 807 fprintf(logfile, "\n");
778 808 fprintf(logfile, "OP:\n");
779 809 dump_ops(gen_opc_buf, gen_opparam_buf);
... ...