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