No subject
Wed Mar 7 09:13:06 PST 2012
[...]
IF (NestingLevel > 1)
THEN FOR i <- 1 to (NestingLevel - 1)
DO
IF 64-Bit Mode (StackSize =3D 64)
THEN
RBP <- RBP - 8;
Push([RBP]); (* Quadword push *)
ELSE IF OperandSize =3D 32
THEN
IF StackSize =3D 32
EBP <- EBP - 4;
Push([EBP]); (* Doubleword push *)
ELSE (* StackSize =3D 16 *)
BP <- BP - 4;
Push([BP]); (* Doubleword push *)
FI;
FI;
ELSE (* OperandSize =3D 16 *)
IF StackSize =3D 32
THEN
EBP <- EBP - 2;
Push([EBP]); (* Word push *)
ELSE (* StackSize =3D 16 *)
BP <- BP - 2;
Push([BP]); (* Word push *)
FI;
FI;
OD;
FI;
[...]
I believe the 0x66 prefix only affects OperandSize, not StackSize. So
according to the manual, it should be BP, not EBP.
In any case, It won't be a problem, because the 16 high bits of EBP
will most likely be zero in real-mode code.
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_BP -=3D=
2;
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0push_word(fetch=
_data_word_abs(M.x86.R_SS, M.x86.R_BP));
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> - =C2=A0 =C2=A0 =C2=A0 =C2=A0push_word(frame_pointer);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0push_word(frame_pointer);
>> + =C2=A0 =C2=A0}
>> =C2=A0 =C2=A0 =C2=A0M.x86.R_BP =3D frame_pointer;
>> =C2=A0 =C2=A0 =C2=A0M.x86.R_SP =3D (u16)(M.x86.R_SP - local);
>> =C2=A0 =C2=A0 =C2=A0DECODE_CLEAR_SEGOVR();
>
>
>> @@ -8827,8 +8844,13 @@ static void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED=
(op1))
>> =C2=A0 =C2=A0 =C2=A0DECODE_PRINTF2("%x\n", imm);
>> =C2=A0 =C2=A0 =C2=A0 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
>> =C2=A0 =C2=A0 =C2=A0 TRACE_AND_STEP();
>> - =C2=A0 =C2=A0M.x86.R_IP =3D pop_word();
>> - =C2=A0 =C2=A0M.x86.R_CS =3D pop_word();
>> + =C2=A0 =C2=A0if (M.x86.mode & SYSMODE_PREFIX_DATA) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_IP =3D pop_long();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_CS =3D pop_long() & 0xffff;
>> + =C2=A0 =C2=A0} else {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_IP =3D pop_word();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_CS =3D pop_word();
>> + =C2=A0 =C2=A0}
>> =C2=A0 =C2=A0 =C2=A0M.x86.R_SP +=3D imm;
>> =C2=A0 =C2=A0 =C2=A0DECODE_CLEAR_SEGOVR();
>> =C2=A0 =C2=A0 =C2=A0END_OF_INSTR();
>> @@ -8844,8 +8866,13 @@ static void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1=
))
>> =C2=A0 =C2=A0 =C2=A0DECODE_PRINTF("RETF\n");
>> =C2=A0 =C2=A0 =C2=A0 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
>> =C2=A0 =C2=A0 =C2=A0 TRACE_AND_STEP();
>> - =C2=A0 =C2=A0M.x86.R_IP =3D pop_word();
>> - =C2=A0 =C2=A0M.x86.R_CS =3D pop_word();
>> + =C2=A0 =C2=A0if (M.x86.mode & SYSMODE_PREFIX_DATA) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_IP =3D pop_long();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_CS =3D pop_long() & 0xffff;
>> + =C2=A0 =C2=A0} else {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_IP =3D pop_word();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_CS =3D pop_word();
>> + =C2=A0 =C2=A0}
>> =C2=A0 =C2=A0 =C2=A0DECODE_CLEAR_SEGOVR();
>> =C2=A0 =C2=A0 =C2=A0END_OF_INSTR();
>> =C2=A0}
>> @@ -8939,9 +8966,15 @@ static void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
>>
>> =C2=A0 =C2=A0 =C2=A0TRACE_AND_STEP();
>>
>> - =C2=A0 =C2=A0M.x86.R_IP =3D pop_word();
>> - =C2=A0 =C2=A0M.x86.R_CS =3D pop_word();
>> - =C2=A0 =C2=A0M.x86.R_FLG =3D pop_word();
>> + =C2=A0 =C2=A0if (M.x86.mode & SYSMODE_PREFIX_DATA) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_IP =3D pop_long();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_CS =3D pop_long() & 0xffff;
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_FLG =3D pop_long();
>> + =C2=A0 =C2=A0} else {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_IP =3D pop_word();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_CS =3D pop_word();
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0M.x86.R_FLG =3D pop_word();
>> + =C2=A0 =C2=A0}
>> =C2=A0 =C2=A0 =C2=A0DECODE_CLEAR_SEGOVR();
>> =C2=A0 =C2=A0 =C2=A0END_OF_INSTR();
>> =C2=A0}
>
> On these three hunks, when on 32-bit mode shouldn't the registers be
> M.x86.R_EIP and M.x86.R_EFLG?
>
You're absolutely right, and in addition, it seems that some of the
bits in EFLAGS must be preserved by the iret instruction, as described
in the manual:
[...]
REAL-ADDRESS-MODE;
IF OperandSize =3D 32
THEN
IF top 12 bytes of stack not within stack limits
THEN #SS; FI;
tempEIP <- 4 bytes at end of stack
IF tempEIP[31:16] is not zero THEN #GP(0); FI;
EIP <- Pop();
CS <- Pop(); (* 32-bit pop, high-order 16 bits discarded *)
tempEFLAGS <- Pop();
EFLAGS <- (tempEFLAGS AND 257FD5H) OR (EFLAGS AND 1A0000H);
ELSE (* OperandSize =3D 16 *)
IF top 6 bytes of stack are not within stack limits
THEN #SS; FI;
EIP <- Pop(); (* 16-bit pop; clear upper 16 bits *)
CS <- Pop(); (* 16-bit pop *)
EFLAGS[15:0] <- Pop();
FI;
END;
[...]
I will respin a patch shortly.
--=20
Julian
More information about the xorg-devel
mailing list