@@ -1929,20 +1929,6 @@ static bool valid_bnd(cs_struct *h, unsigned int opcode)
19291929 // not found
19301930 return false;
19311931}
1932-
1933- // return true if the opcode is XCHG [mem]
1934- static bool xchg_mem (unsigned int opcode )
1935- {
1936- switch (opcode ) {
1937- default :
1938- return false;
1939- case X86_XCHG8rm :
1940- case X86_XCHG16rm :
1941- case X86_XCHG32rm :
1942- case X86_XCHG64rm :
1943- return true;
1944- }
1945- }
19461932#endif
19471933
19481934// given MCInst's id, find out if this insn is valid for REP prefix
@@ -2112,106 +2098,79 @@ bool X86_lockrep(MCInst *MI, SStream *O)
21122098 unsigned int opcode ;
21132099 bool res = false;
21142100
2115- switch (MI -> x86_prefix [0 ]) {
2101+ #ifndef CAPSTONE_DIET
2102+ switch (MI -> xAcquireRelease ) {
2103+ case 0xF2 :
2104+ SStream_concat (O , "xacquire|" );
2105+ break ;
2106+ case 0xF3 :
2107+ SStream_concat (O , "xrelease|" );
2108+ break ;
21162109 default :
21172110 break ;
2118- case 0xf0 :
2119- #ifndef CAPSTONE_DIET
2120- if (MI -> xAcquireRelease == 0xf2 )
2121- SStream_concat (O , "xacquire|lock|" );
2122- else if (MI -> xAcquireRelease == 0xf3 )
2123- SStream_concat (O , "xrelease|lock|" );
2124- else
2125- SStream_concat (O , "lock|" );
2111+ }
21262112#endif
2127- break ;
2128- case 0xf2 : // repne
2129- opcode = MCInst_getOpcode (MI );
21302113
2131- #ifndef CAPSTONE_DIET // only care about memonic in standard (non-diet) mode
2132- if (xchg_mem (opcode ) && MI -> xAcquireRelease ) {
2133- SStream_concat (O , "xacquire|" );
2134- } else if (valid_repne (MI -> csh , opcode )) {
2135- SStream_concat (O , "repne|" );
2136- add_cx (MI );
2137- } else if (valid_bnd (MI -> csh , opcode )) {
2138- SStream_concat (O , "bnd|" );
2139- } else {
2140- // invalid prefix
2141- MI -> x86_prefix [0 ] = 0 ;
2142-
2143- // handle special cases
2144- #ifndef CAPSTONE_X86_REDUCE
2145- #if 0
2146- if (opcode == X86_MULPDrr ) {
2147- MCInst_setOpcode (MI , X86_MULSDrr );
2148- SStream_concat0 (O , "mulsd\t" );
2149- res = true;
2150- }
2151- #endif
2152- #endif
2153- }
2154- #else // diet mode -> only patch opcode in special cases
2155- if (!valid_repne (MI -> csh , opcode )) {
2156- MI -> x86_prefix [0 ] = 0 ;
2114+ if (MI -> xAcquireRelease ) {
2115+ if (MI -> x86Lock ) {
2116+ // Force LOCK prefix as group 0 prefix for XACQUIRE and XRELEASE if a LOCK is also present.
2117+ // This is an arbitrary choice, since there are effectively two group 0 prefixes present.
2118+ // The Intel SDM is not clear on how we should interpret group 0 in this case. It states:
2119+ // "it is only useful to include up to one prefix code from each of the four groups"
2120+ // ...and then defines instructions where both an F2/F3 and F0 are useful anyway.
2121+ MI -> x86_prefix [0 ] = 0xF0 ;
21572122 }
2158- #ifndef CAPSTONE_X86_REDUCE
2159- #if 0
2160- // handle special cases
2161- if (opcode == X86_MULPDrr ) {
2162- MCInst_setOpcode (MI , X86_MULSDrr );
2123+ } else {
2124+ switch (MI -> x86_prefix [0 ]) {
2125+ case 0xF2 :
2126+ opcode = MCInst_getOpcode (MI );
2127+ #ifndef CAPSTONE_DIET
2128+ if (valid_repne (MI -> csh , opcode )) {
2129+ SStream_concat (O , "repne|" );
2130+ add_cx (MI );
2131+ } else if (valid_bnd (MI -> csh , opcode )) {
2132+ SStream_concat (O , "bnd|" );
2133+ } else {
2134+ // invalid prefix
2135+ MI -> x86_prefix [0 ] = 0 ;
21632136 }
2164- #endif
2165- #endif
2166- #endif
2167- break ;
2168-
2169- case 0xf3 :
2170- opcode = MCInst_getOpcode (MI );
2171-
2172- #ifndef CAPSTONE_DIET // only care about memonic in standard (non-diet) mode
2173- if (xchg_mem (opcode ) && MI -> xAcquireRelease ) {
2174- SStream_concat (O , "xrelease|" );
2175- } else if (valid_rep (MI -> csh , opcode )) {
2176- SStream_concat (O , "rep|" );
2177- add_cx (MI );
2178- } else if (valid_repe (MI -> csh , opcode )) {
2179- SStream_concat (O , "repe|" );
2180- add_cx (MI );
2181- } else if (valid_ret_repz (MI -> csh , opcode )) {
2182- SStream_concat (O , "repz|" );
2183- } else {
2184- // invalid prefix
2185- MI -> x86_prefix [0 ] = 0 ;
2186-
2187- // handle special cases
2188- #ifndef CAPSTONE_X86_REDUCE
2189- #if 0
2190- // FIXME: remove this special case?
2191- if (opcode == X86_MULPDrr ) {
2192- MCInst_setOpcode (MI , X86_MULSSrr );
2193- SStream_concat0 (O , "mulss\t" );
2194- res = true;
2195- }
2196- #endif
2197- #endif
2198- }
2199- #else // diet mode -> only patch opcode in special cases
2200- if (!valid_rep (MI -> csh , opcode ) &&
2201- !valid_repe (MI -> csh , opcode )) {
2202- MI -> x86_prefix [0 ] = 0 ;
2203- }
2204- #ifndef CAPSTONE_X86_REDUCE
2205- #if 0
2206- // handle special cases
2207- // FIXME: remove this special case?
2208- if (opcode == X86_MULPDrr ) {
2209- MCInst_setOpcode (MI , X86_MULSSrr );
2137+ #else
2138+ if (!valid_repne (MI -> csh , opcode )) {
2139+ MI -> x86_prefix [0 ] = 0 ;
22102140 }
22112141#endif
2142+ break ;
2143+ case 0xF3 :
2144+ opcode = MCInst_getOpcode (MI );
2145+ #ifndef CAPSTONE_DIET
2146+ if (valid_rep (MI -> csh , opcode )) {
2147+ SStream_concat (O , "rep|" );
2148+ add_cx (MI );
2149+ } else if (valid_repe (MI -> csh , opcode )) {
2150+ SStream_concat (O , "repe|" );
2151+ add_cx (MI );
2152+ } else if (valid_ret_repz (MI -> csh , opcode )) {
2153+ SStream_concat (O , "repz|" );
2154+ } else {
2155+ // invalid prefix
2156+ MI -> x86_prefix [0 ] = 0 ;
2157+ }
2158+ #else
2159+ if (!valid_rep (MI -> csh , opcode ) &&
2160+ !valid_repe (MI -> csh , opcode )) {
2161+ MI -> x86_prefix [0 ] = 0 ;
2162+ }
22122163#endif
2213- #endif
2214- break ;
2164+ break ;
2165+ default :
2166+ break ;
2167+ }
2168+ }
2169+
2170+ // LOCK and F2/F3 may both be present (for XACQUIRE/XRELEASE).
2171+ // There are also XRELEASEs that can be LOCKless.
2172+ if (MI -> x86Lock ) {
2173+ SStream_concat (O , "lock|" );
22152174 }
22162175
22172176 switch (MI -> x86_prefix [1 ]) {
0 commit comments