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,24 +643,43 @@ void OPPROTO op_next_insn(void)
643 env->npc = env->npc + 4; 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 if (T2) { 654 if (T2) {
649 - env->npc = PARAM1; 655 + env->npc = PARAM2 + 4;
  656 + JUMP_TB(op_branch2, PARAM1, 0, PARAM2);
650 } else { 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 FORCE_RET(); 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 if (T2) { 678 if (T2) {
659 - env->pc = PARAM2;  
660 env->npc = PARAM1; 679 env->npc = PARAM1;
661 } else { 680 } else {
662 - env->pc = PARAM2 + 4;  
663 - env->npc = PARAM2 + 8; 681 + env->npc = PARAM2;
664 } 682 }
665 FORCE_RET(); 683 FORCE_RET();
666 } 684 }
  685 +
target-sparc/translate.c
@@ -42,9 +42,14 @@ @@ -42,9 +42,14 @@
42 42
43 #define DEBUG_DISAS 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 typedef struct DisasContext { 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 int is_br; 53 int is_br;
49 struct TranslationBlock *tb; 54 struct TranslationBlock *tb;
50 } DisasContext; 55 } DisasContext;
@@ -306,6 +311,31 @@ static inline void gen_movl_T1_reg(int reg) @@ -306,6 +311,31 @@ static inline void gen_movl_T1_reg(int reg)
306 gen_movl_TN_reg(reg, 1); 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 static void gen_cond(int cond) 339 static void gen_cond(int cond)
310 { 340 {
311 switch (cond) { 341 switch (cond) {
@@ -378,25 +408,23 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn) @@ -378,25 +408,23 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
378 } else if (cond == 0x8) { 408 } else if (cond == 0x8) {
379 /* unconditional taken */ 409 /* unconditional taken */
380 if (a) { 410 if (a) {
381 - dc->pc = (uint8_t *) target; 411 + dc->pc = target;
382 dc->npc = dc->pc + 4; 412 dc->npc = dc->pc + 4;
383 } else { 413 } else {
384 dc->pc = dc->npc; 414 dc->pc = dc->npc;
385 - dc->npc = (uint8_t *) target; 415 + dc->npc = target;
386 } 416 }
387 } else { 417 } else {
  418 + flush_T2(dc);
388 gen_cond(cond); 419 gen_cond(cond);
389 if (a) { 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 dc->is_br = 1; 422 dc->is_br = 1;
393 - dc->pc = NULL;  
394 - dc->npc = NULL;  
395 } else { 423 } else {
396 dc->pc = dc->npc; 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,18 +437,11 @@ static int sign_extend(int x, int len)
409 return (x << len) >> len; 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 static void disas_sparc_insn(DisasContext * dc) 440 static void disas_sparc_insn(DisasContext * dc)
420 { 441 {
421 unsigned int insn, opc, rs1, rs2, rd; 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 opc = GET_FIELD(insn, 0, 1); 445 opc = GET_FIELD(insn, 0, 1);
425 446
426 rd = GET_FIELD(insn, 2, 6); 447 rd = GET_FIELD(insn, 2, 6);
@@ -458,9 +479,9 @@ static void disas_sparc_insn(DisasContext * dc) @@ -458,9 +479,9 @@ static void disas_sparc_insn(DisasContext * dc)
458 479
459 gen_op_movl_T0_im((long) (dc->pc)); 480 gen_op_movl_T0_im((long) (dc->pc));
460 gen_movl_T0_reg(15); 481 gen_movl_T0_reg(15);
461 - target = (long) dc->pc + target; 482 + target = dc->pc + target;
462 dc->pc = dc->npc; 483 dc->pc = dc->npc;
463 - dc->npc = (uint8_t *) target; 484 + dc->npc = target;
464 } 485 }
465 goto jmp_insn; 486 goto jmp_insn;
466 case 2: /* FPU & Logical Operations */ 487 case 2: /* FPU & Logical Operations */
@@ -625,7 +646,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -625,7 +646,7 @@ static void disas_sparc_insn(DisasContext * dc)
625 gen_movl_T0_reg(rd); 646 gen_movl_T0_reg(rd);
626 } 647 }
627 dc->pc = dc->npc; 648 dc->pc = dc->npc;
628 - dc->npc = NULL; 649 + dc->npc = DYNAMIC_PC;
629 } 650 }
630 goto jmp_insn; 651 goto jmp_insn;
631 case 0x3b: /* flush */ 652 case 0x3b: /* flush */
@@ -705,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -705,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc)
705 gen_op_sth(); 726 gen_op_sth();
706 break; 727 break;
707 case 0x7: 728 case 0x7:
  729 + flush_T2(dc);
708 gen_movl_reg_T2(rd + 1); 730 gen_movl_reg_T2(rd + 1);
709 gen_op_std(); 731 gen_op_std();
710 break; 732 break;
@@ -713,19 +735,21 @@ static void disas_sparc_insn(DisasContext * dc) @@ -713,19 +735,21 @@ static void disas_sparc_insn(DisasContext * dc)
713 } 735 }
714 } 736 }
715 /* default case for non jump instructions */ 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 dc->pc = dc->npc; 746 dc->pc = dc->npc;
718 dc->npc = dc->npc + 4; 747 dc->npc = dc->npc + 4;
719 - } else {  
720 - dc->pc = NULL;  
721 - gen_op_next_insn();  
722 } 748 }
723 jmp_insn:; 749 jmp_insn:;
724 return; 750 return;
725 illegal_insn: 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 gen_op_exception(TT_ILL_INSN); 753 gen_op_exception(TT_ILL_INSN);
730 dc->is_br = 1; 754 dc->is_br = 1;
731 } 755 }
@@ -733,7 +757,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -733,7 +757,7 @@ static void disas_sparc_insn(DisasContext * dc)
733 static inline int gen_intermediate_code_internal(TranslationBlock * tb, 757 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
734 int spc) 758 int spc)
735 { 759 {
736 - uint8_t *pc_start, *last_pc; 760 + target_ulong pc_start, last_pc;
737 uint16_t *gen_opc_end; 761 uint16_t *gen_opc_end;
738 DisasContext dc1, *dc = &dc1; 762 DisasContext dc1, *dc = &dc1;
739 763
@@ -743,9 +767,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, @@ -743,9 +767,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
743 exit(0); 767 exit(0);
744 } 768 }
745 dc->tb = tb; 769 dc->tb = tb;
746 - pc_start = (uint8_t *) tb->pc; 770 + pc_start = tb->pc;
747 dc->pc = pc_start; 771 dc->pc = pc_start;
748 - dc->npc = (uint8_t *) tb->cs_base; 772 + dc->npc = (target_ulong) tb->cs_base;
749 773
750 gen_opc_ptr = gen_opc_buf; 774 gen_opc_ptr = gen_opc_buf;
751 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 775 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
@@ -761,19 +785,25 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, @@ -761,19 +785,25 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
761 break; 785 break;
762 } while ((gen_opc_ptr < gen_opc_end) && 786 } while ((gen_opc_ptr < gen_opc_end) &&
763 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); 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 *gen_opc_ptr = INDEX_op_end; 801 *gen_opc_ptr = INDEX_op_end;
772 #ifdef DEBUG_DISAS 802 #ifdef DEBUG_DISAS
773 if (loglevel) { 803 if (loglevel) {
774 fprintf(logfile, "--------------\n"); 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 fprintf(logfile, "\n"); 807 fprintf(logfile, "\n");
778 fprintf(logfile, "OP:\n"); 808 fprintf(logfile, "OP:\n");
779 dump_ops(gen_opc_buf, gen_opparam_buf); 809 dump_ops(gen_opc_buf, gen_opparam_buf);