mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
hvm: Fix get_immediate() in mmio decoder by reverting Dexuan Cui's
change that breaks the case mod==0, rm==4, sib&7==5. That is, disp32(scaled-index). Also simplify get_immediate with sign extension. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
2124081013
commit
7584e4be28
1 file changed
+8
-23
@@ -221,6 +221,7 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst
|
||||
|
||||
inst++; //skip ModR/M byte
|
||||
if ( ad_size != WORD && mod != 3 && rm == 4 ) {
|
||||
rm = *inst & 7;
|
||||
inst++; //skip SIB byte
|
||||
}
|
||||
|
||||
@@ -256,31 +257,15 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require
|
||||
* the src immediate operand be sign-extented befere the op is executed. Here
|
||||
* we always sign-extend the operand to a "unsigned long" variable.
|
||||
*
|
||||
* Note: to simplify the logic here, the sign-extension here may be performed
|
||||
* redundantly against some instructions, like "MOV $imm16, r/m16" -- however
|
||||
* this is harmless, since we always remember the operand's size.
|
||||
*/
|
||||
static inline unsigned long get_immediate_sign_ext(int ad_size,
|
||||
const unsigned char *inst,
|
||||
int op_size)
|
||||
static inline unsigned long get_immediate_sign_ext(
|
||||
int ad_size, const unsigned char *inst, int op_size)
|
||||
{
|
||||
unsigned long result = get_immediate(ad_size, inst, op_size);
|
||||
|
||||
if ( op_size == QUAD )
|
||||
op_size = LONG;
|
||||
|
||||
ASSERT( op_size == BYTE || op_size == WORD || op_size == LONG );
|
||||
|
||||
if ( result & (1UL << ((8*op_size) - 1)) )
|
||||
{
|
||||
unsigned long mask = ~0UL >> (8 * (sizeof(mask) - op_size));
|
||||
result = ~mask | (result & mask);
|
||||
}
|
||||
return result;
|
||||
if ( op_size == BYTE )
|
||||
return (int8_t)result;
|
||||
if ( op_size == WORD )
|
||||
return (int16_t)result;
|
||||
return (int32_t)result;
|
||||
}
|
||||
|
||||
static inline int get_index(const unsigned char *inst, unsigned char rex)
|
||||
|
||||