@@ -645,6 +645,158 @@ static void load_step_to_reg_ir1(IR2_OPND *p_step_opnd, IR1_OPND *opnd_ir1)
645645 ra_free_temp (tmp_step );
646646}
647647
648+ #ifdef TARGET_X86_64
649+ static bool tr_can_fast_rep_string_b (IR1_INST * pir1 , IR1_OPCODE insn )
650+ {
651+ return CODEIS64 &&
652+ ir1_prefix (pir1 ) == dt_X86_PREFIX_REP &&
653+ pir1 -> info -> id == insn &&
654+ pir1 -> info -> x86 .prefix [3 ] != 0x67 ;
655+ }
656+
657+ static void tr_emit_rep_string_df_guard (IR2_OPND label_slow )
658+ {
659+ IR2_OPND df_opnd = ra_alloc_itemp ();
660+ IR2_OPND eflags_opnd = ra_alloc_eflags ();
661+
662+ la_andi (df_opnd , eflags_opnd , 1 << DF_BIT_INDEX );
663+ la_bne (df_opnd , zero_ir2_opnd , label_slow );
664+
665+ ra_free_temp (df_opnd );
666+ }
667+
668+ static void tr_emit_finish_fast_rep_string (IR2_OPND ecx_opnd ,
669+ IR2_OPND label_exit )
670+ {
671+ la_or (ecx_opnd , zero_ir2_opnd , zero_ir2_opnd );
672+ store_ireg_to_ir1 (ecx_opnd , & rcx_ir1_opnd , false);
673+ la_b (label_exit );
674+ }
675+
676+ static bool tr_emit_fast_rep_movsb (IR1_INST * pir1 , IR2_OPND rsi_opnd ,
677+ IR2_OPND rdi_opnd , IR2_OPND rcx_opnd ,
678+ IR2_OPND label_exit )
679+ {
680+ if (!tr_can_fast_rep_string_b (pir1 , dt_X86_INS_MOVSB )) {
681+ return false;
682+ }
683+
684+ IR2_OPND label_slow = ra_alloc_label ();
685+ IR2_OPND label_no_overlap = ra_alloc_label ();
686+ IR2_OPND label_qword_done = ra_alloc_label ();
687+ IR2_OPND label_qword_loop = ra_alloc_label ();
688+ IR2_OPND label_tail_done = ra_alloc_label ();
689+ IR2_OPND label_tail_loop = ra_alloc_label ();
690+ IR2_OPND qwords = ra_alloc_itemp ();
691+ IR2_OPND tail = ra_alloc_itemp ();
692+ IR2_OPND value = ra_alloc_itemp ();
693+ IR2_OPND overlap = ra_alloc_itemp ();
694+
695+ tr_emit_rep_string_df_guard (label_slow );
696+
697+ la_bgeu (rsi_opnd , rdi_opnd , label_no_overlap );
698+ la_sub_d (overlap , rdi_opnd , rsi_opnd );
699+ la_bltu (overlap , rcx_opnd , label_slow );
700+
701+ la_label (label_no_overlap );
702+ la_srli_d (qwords , rcx_opnd , 3 );
703+ la_andi (tail , rcx_opnd , 7 );
704+
705+ la_beq (qwords , zero_ir2_opnd , label_qword_done );
706+ la_label (label_qword_loop );
707+ la_ld_d (value , rsi_opnd , 0 );
708+ la_st_d (value , rdi_opnd , 0 );
709+ la_addi_d (rsi_opnd , rsi_opnd , 8 );
710+ la_addi_d (rdi_opnd , rdi_opnd , 8 );
711+ la_addi_d (qwords , qwords , -1 );
712+ la_bne (qwords , zero_ir2_opnd , label_qword_loop );
713+
714+ la_label (label_qword_done );
715+ la_beq (tail , zero_ir2_opnd , label_tail_done );
716+ la_label (label_tail_loop );
717+ la_ld_bu (value , rsi_opnd , 0 );
718+ la_st_b (value , rdi_opnd , 0 );
719+ la_addi_d (rsi_opnd , rsi_opnd , 1 );
720+ la_addi_d (rdi_opnd , rdi_opnd , 1 );
721+ la_addi_d (tail , tail , -1 );
722+ la_bne (tail , zero_ir2_opnd , label_tail_loop );
723+
724+ la_label (label_tail_done );
725+ tr_emit_finish_fast_rep_string (rcx_opnd , label_exit );
726+
727+ la_label (label_slow );
728+
729+ ra_free_temp (qwords );
730+ ra_free_temp (tail );
731+ ra_free_temp (value );
732+ ra_free_temp (overlap );
733+ return true;
734+ }
735+
736+ static void tr_replicate_byte_to_dword (IR2_OPND dst , IR2_OPND src ,
737+ IR2_OPND tmp )
738+ {
739+ la_andi (dst , src , 0xff );
740+ la_slli_d (tmp , dst , 8 );
741+ la_or (dst , dst , tmp );
742+ la_slli_d (tmp , dst , 16 );
743+ la_or (dst , dst , tmp );
744+ la_slli_d (tmp , dst , 32 );
745+ la_or (dst , dst , tmp );
746+ }
747+
748+ static bool tr_emit_fast_rep_stosb (IR1_INST * pir1 , IR2_OPND rdi_opnd ,
749+ IR2_OPND rcx_opnd , IR2_OPND value_opnd ,
750+ IR2_OPND label_exit )
751+ {
752+ if (!tr_can_fast_rep_string_b (pir1 , dt_X86_INS_STOSB )) {
753+ return false;
754+ }
755+
756+ IR2_OPND label_slow = ra_alloc_label ();
757+ IR2_OPND label_qword_done = ra_alloc_label ();
758+ IR2_OPND label_qword_loop = ra_alloc_label ();
759+ IR2_OPND label_tail_done = ra_alloc_label ();
760+ IR2_OPND label_tail_loop = ra_alloc_label ();
761+ IR2_OPND qwords = ra_alloc_itemp ();
762+ IR2_OPND tail = ra_alloc_itemp ();
763+ IR2_OPND fill = ra_alloc_itemp ();
764+ IR2_OPND tmp = ra_alloc_itemp ();
765+
766+ tr_emit_rep_string_df_guard (label_slow );
767+
768+ tr_replicate_byte_to_dword (fill , value_opnd , tmp );
769+ la_srli_d (qwords , rcx_opnd , 3 );
770+ la_andi (tail , rcx_opnd , 7 );
771+
772+ la_beq (qwords , zero_ir2_opnd , label_qword_done );
773+ la_label (label_qword_loop );
774+ la_st_d (fill , rdi_opnd , 0 );
775+ la_addi_d (rdi_opnd , rdi_opnd , 8 );
776+ la_addi_d (qwords , qwords , -1 );
777+ la_bne (qwords , zero_ir2_opnd , label_qword_loop );
778+
779+ la_label (label_qword_done );
780+ la_beq (tail , zero_ir2_opnd , label_tail_done );
781+ la_label (label_tail_loop );
782+ la_st_b (fill , rdi_opnd , 0 );
783+ la_addi_d (rdi_opnd , rdi_opnd , 1 );
784+ la_addi_d (tail , tail , -1 );
785+ la_bne (tail , zero_ir2_opnd , label_tail_loop );
786+
787+ la_label (label_tail_done );
788+ tr_emit_finish_fast_rep_string (rcx_opnd , label_exit );
789+
790+ la_label (label_slow );
791+
792+ ra_free_temp (qwords );
793+ ra_free_temp (tail );
794+ ra_free_temp (fill );
795+ ra_free_temp (tmp );
796+ return true;
797+ }
798+ #endif
799+
648800bool translate_movs (IR1_INST * pir1 )
649801{
650802 IR2_OPND esi_opnd = ra_alloc_gpr (esi_index );
@@ -769,6 +921,10 @@ bool translate_movs(IR1_INST *pir1)
769921 lsassert (0 );
770922 }
771923
924+ #ifdef TARGET_X86_64
925+ tr_emit_fast_rep_movsb (pir1 , esi_opnd , edi_opnd , ecx_opnd , label_exit );
926+ #endif
927+
772928 /* 2. preparations outside the loop */
773929 IR2_OPND step_opnd = ra_alloc_itemp ();
774930 load_step_to_reg_ir1 (& step_opnd , mem_di );
@@ -970,6 +1126,10 @@ bool translate_stos(IR1_INST *pir1)
9701126 }
9711127 IR2_OPND eax_value_opnd =
9721128 load_ireg_from_ir1 (opnd_eax , SIGN_EXTENSION , false);
1129+ #ifdef TARGET_X86_64
1130+ tr_emit_fast_rep_stosb (pir1 , edi_opnd , ecx_opnd , eax_value_opnd ,
1131+ label_exit );
1132+ #endif
9731133 IR2_OPND step_opnd = ra_alloc_itemp ();
9741134 load_step_to_reg_ir1 (& step_opnd , opnd_di );
9751135
0 commit comments