@@ -4792,12 +4792,12 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
47924792{
47934793 TCGContext * tcg_ctx = s -> uc -> tcg_ctx ;
47944794 CPUX86State * env = cpu -> env_ptr ;
4795- int b , prefixes ;
4795+ int b , prefixes , prefix_count ;
47964796 int shift ;
47974797 MemOp ot , aflag , dflag ;
47984798 int modrm , reg , rm , mod , op , opreg , val ;
47994799 target_ulong next_eip , tval ;
4800- int rex_w , rex_r ;
4800+ int rex_w , rex_r , rex_byte , rex_index ;
48014801 target_ulong pc_start = s -> base .pc_next ;
48024802 TCGOp * tcg_op , * prev_op = NULL ;
48034803 bool insn_hook = false;
@@ -4854,43 +4854,57 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
48544854 prefixes = 0 ;
48554855 rex_w = -1 ;
48564856 rex_r = 0 ;
4857+ rex_byte = 0 ;
4858+ rex_index = -1 ;
4859+ prefix_count = 0 ;
48574860
48584861 next_byte :
48594862 b = x86_ldub_code (env , s );
48604863 /* Collect prefixes. */
48614864 switch (b ) {
48624865 case 0xf3 :
48634866 prefixes |= PREFIX_REPZ ;
4867+ prefix_count ++ ;
48644868 goto next_byte ;
48654869 case 0xf2 :
48664870 prefixes |= PREFIX_REPNZ ;
4871+ prefix_count ++ ;
48674872 goto next_byte ;
48684873 case 0xf0 :
48694874 prefixes |= PREFIX_LOCK ;
4875+ prefix_count ++ ;
48704876 goto next_byte ;
48714877 case 0x2e :
48724878 s -> override = R_CS ;
4879+ prefix_count ++ ;
48734880 goto next_byte ;
48744881 case 0x36 :
48754882 s -> override = R_SS ;
4883+ prefix_count ++ ;
48764884 goto next_byte ;
48774885 case 0x3e :
48784886 s -> override = R_DS ;
4887+ prefix_count ++ ;
48794888 goto next_byte ;
48804889 case 0x26 :
48814890 s -> override = R_ES ;
4891+ prefix_count ++ ;
48824892 goto next_byte ;
48834893 case 0x64 :
48844894 s -> override = R_FS ;
4895+ prefix_count ++ ;
48854896 goto next_byte ;
48864897 case 0x65 :
48874898 s -> override = R_GS ;
4899+ prefix_count ++ ;
48884900 goto next_byte ;
48894901 case 0x66 :
48904902 prefixes |= PREFIX_DATA ;
4903+ prefix_count ++ ;
48914904 goto next_byte ;
48924905 case 0x67 :
48934906 prefixes |= PREFIX_ADR ;
4907+ prefix_count ++ ;
48944908 goto next_byte ;
48954909#ifdef TARGET_X86_64
48964910 case 0x40 :
@@ -4910,13 +4924,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
49104924 case 0x4e :
49114925 case 0x4f :
49124926 if (CODE64 (s )) {
4913- /* REX prefix */
4914- rex_w = (b >> 3 ) & 1 ;
4915- rex_r = (b & 0x4 ) << 1 ;
4916- s -> rex_x = (b & 0x2 ) << 2 ;
4917- REX_B (s ) = (b & 0x1 ) << 3 ;
4918- /* select uniform byte register addressing */
4919- s -> x86_64_hregs = true;
4927+ rex_byte = b ;
4928+ rex_index = prefix_count ;
4929+ prefix_count ++ ;
49204930 goto next_byte ;
49214931 }
49224932 break ;
@@ -4944,7 +4954,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
49444954 goto illegal_op ;
49454955 }
49464956#ifdef TARGET_X86_64
4947- if (s -> x86_64_hregs ) {
4957+ if (rex_byte != 0 ) {
49484958 goto illegal_op ;
49494959 }
49504960#endif
@@ -4979,11 +4989,23 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
49794989 s -> vex_l = (vex3 >> 2 ) & 1 ;
49804990 prefixes |= pp_prefix [vex3 & 3 ] | PREFIX_VEX ;
49814991 }
4992+ prefix_count ++ ;
49824993 break ;
49834994 }
49844995
49854996 /* Post-process prefixes. */
49864997 if (CODE64 (s )) {
4998+ /* 2.2.1: A REX prefix is ignored when it does not immediately precede the opcode byte */
4999+ if (rex_byte != 0 && rex_index + 1 == prefix_count ) {
5000+ /* REX prefix */
5001+ rex_w = (rex_byte >> 3 ) & 1 ;
5002+ rex_r = (rex_byte & 0x4 ) << 1 ;
5003+ s -> rex_x = (rex_byte & 0x2 ) << 2 ;
5004+ REX_B (s ) = (rex_byte & 0x1 ) << 3 ;
5005+ /* select uniform byte register addressing */
5006+ s -> x86_64_hregs = true;
5007+ }
5008+
49875009 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
49885010 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
49895011 over 0x66 if both are present. */
@@ -7807,12 +7829,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
78077829 gen_op_mov_reg_v (s , MO_64 , reg , s -> T0 );
78087830 } else
78097831#endif
7810- {
7832+ if ( dflag == MO_32 ) {
78117833 gen_op_mov_v_reg (s , MO_32 , s -> T0 , reg );
78127834 tcg_gen_ext32u_tl (tcg_ctx , s -> T0 , s -> T0 );
78137835 tcg_gen_bswap32_tl (tcg_ctx , s -> T0 , s -> T0 );
78147836 gen_op_mov_reg_v (s , MO_32 , reg , s -> T0 );
78157837 }
7838+ else {
7839+ tcg_gen_movi_tl (tcg_ctx , s -> T0 , 0 );
7840+ gen_op_mov_reg_v (s , MO_16 , reg , s -> T0 );
7841+ }
78167842 break ;
78177843 case 0xd6 : /* salc */
78187844 if (CODE64 (s ))
0 commit comments