Opcode Instruction Clocks Description CF IRET 22,pm=38 Interrupt return (far return and pop flags) CF IRET pm=82 Interrupt return to lesser privilege CF IRET ts Interrupt return, different task (NT = 1) CF IRETD 22,pm=38 Interrupt return (far return and pop flags) CF IRETD pm=82 Interrupt return to lesser privilege CF IRETD pm=60 Interrupt return to V86 mode CF IRETD ts Interrupt return, different task (NT = 1)Note Values of ts are given by the following table:
New Task Old Task 386 TSS 386 TSS 286 TSS VM = 0 VM = 1 386 TSS VM=0 275 224 271 286 TSS 265 214 232
IF PE = 0 THEN (* Real-address mode *) IF OperandSize = 32 (* Instruction = IRETD *) THEN EIP := Pop(); ELSE (* Instruction = IRET *) IP := Pop(); FI; CS := Pop(); IF OperandSize = 32 (* Instruction = IRETD *) THEN EFLAGS := Pop(); ELSE (* Instruction = IRET *) FLAGS := Pop(); FI; ELSE (* Protected mode *) IF VM = 1 THEN #GP(0); ELSE IF NT = 1 THEN GOTO TASK-RETURN; ELSE IF VM = 1 in flags image on stack THEN GO TO STACK-RETURN-TO-V86; ELSE GOTO STACK-RETURN; FI; FI; FI; FI;STACK-RETURN-TO-V86: (* Interrupted procedure was in V86 mode *) IF return CS selector RPL < > 3 THEN #GP(Return selector); FI; IF top 36 bytes of stack not within limits THEN #SS(0); FI; Examine return CS selector and associated descriptor: IF selector is null, THEN #GP(0); FI; IF selector index not within its descriptor table limits; THEN #GP(Return selector); FI; IF AR byte does not indicate code segment THEN #GP(Return selector); FI; IF code segment DPL not = 3; THEN #GP(Return selector); FI; IF code segment not present THEN #NP(Return selector); FI; Examine return SS selector and associated descriptor: IF selector is null THEN #GP(0); FI; IF selector index not within its descriptor table limits THEN #GP(SS selector); FI; IF selector RPL not = RPL of return CS selector THEN #GP(SS selector); FI; IF AR byte does not indicate a writable data segment THEN #GP(SS selector); FI; IF stack segment DPL not = RPL of return CS selector THEN #GP(SS selector); FI; IF SS not present THEN #NP(SS selector); FI; IF instruction pointer not within code segment limit THEN #GP(0); FI; EFLAGS := SS:[eSP + 8]; (* Sets VM in interrupted routine *) EIP := Pop(); CS := Pop(); (* CS behaves as in 8086, due to VM = 1 *) throwaway := Pop(); (* pop away EFLAGS already read *) ES := Pop(); (* pop 2 words; throw away high-order word *) DS := Pop(); (* pop 2 words; throw away high-order word *) FS := Pop(); (* pop 2 words; throw away high-order word *) GS := Pop(); (* pop 2 words; throw away high-order word *) IF CS.RPL > CPL THEN TempESP := Pop(); TempSS := Pop(); SS:ESP := TempSS:TempESP; FI; (* Resume execution in Virtual 8086 mode *) TASK-RETURN: Examine Back Link Selector in TSS addressed by the current task register: Must specify global in the local/global bit, else #TS(new TSS selector); Index must be within GDT limits, else #TS(new TSS selector); AR byte must specify TSS, else #TS(new TSS selector); New TSS must be busy, else #TS(new TSS selector); TSS must be present, else #NP(new TSS selector); SWITCH-TASKS without nesting to TSS specified by back link selector; Mark the task just abandoned as NOT BUSY; Instruction pointer must be within code segment limit ELSE #GP(0); STACK-RETURN: IF OperandSize=32 THEN Third word on stack must be within stack limits, else #SS(0); ELSE Second word on stack must be within stack limits, else #SS(0); FI; Return CS selector RPL must be >= CPL, else #GP(Return selector); IF return selector RPL = CPL THEN GOTO RETURN-SAME-LEVEL; ELSE GOTO RETURN-OUTER-LEVEL; FI; RETURN-SAME-LEVEL: IF OperandSize=32 THEN Top 12 bytes on stack must be within limits, else #SS(0); Return CS selector (at eSP+4) must be non-null, else #GP(0); ELSE Top 6 bytes on stack must be within limits, else #SS(0); Return CS selector (at eSP+2) must be non-null, else #GP(0); FI; Selector index must be within its descriptor table limits, else #GP (Return selector); AR byte must indicate code segment, else #GP(Return selector); IF non-conforming THEN code segment DPL must = CPL; ELSE #GP(Return selector); FI; IF conforming THEN code segment DPL must be <= CPL, else #GP(Return selector); Segment must be present, else #NP(Return selector); Instruction pointer must be within code segment boundaries, else #GP(0); FI; IF OperandSize=32 THEN Load CS:EIP from stack; Load CS-register with new code segment descriptor; Load EFLAGS with third doubleword from stack; Increment eSP by 12; ELSE Load CS-register with new code segment descriptor; Load FLAGS with third word on stack; Increment eSP by 6; FI; RETURN-OUTER-LEVEL: IF OperandSize=32 THEN Top 20 bytes on stack must be within limits, else #SS(0); ELSE Top 10 bytes on stack must be within limits, else #SS(0); FI; Examine return CS selector and associated descriptor: Selector must be non-null, else #GP(0); Selector index must be within its descriptor table limits; ELSE #GP(Return selector); AR byte must indicate code segment, else #GP(Return selector); IF non-conforming THEN code segment DPL must = CS selector RPL; ELSE #GP(Return selector); FI; IF conforming THEN code segment DPL must be > CPL; ELSE #GP(Return selector); FI; Segment must be present, else #NP(Return selector); Examine return SS selector and associated descriptor: Selector must be non-null, else #GP(0); Selector index must be within its descriptor table limits ELSE #GP(SS selector); Selector RPL must equal the RPL of the return CS selector ELSE #GP(SS selector); AR byte must indicate a writable data segment, else #GP(SS selector); Stack segment DPL must equal the RPL of the return CS selector ELSE #GP(SS selector); SS must be present, else #NP(SS selector); Instruction pointer must be within code segment limit ELSE #GP(0); IF OperandSize=32 THEN Load CS:EIP from stack; Load EFLAGS with values at (eSP+8); ELSE Load CS:IP from stack; Load FLAGS with values at (eSP+4); FI; Load SS:eSP from stack; Set CPL to the RPL of the return CS selector; Load the CS register with the CS descriptor; Load the SS register with the SS descriptor; FOR each of ES, FS, GS, and DS DO; IF the current value of the register is not valid for the outer level; THEN zero the register and clear the valid flag; FI; To be valid, the register setting must satisfy the following properties: Selector index must be within descriptor table limits; AR byte must indicate data or readable code segment; IF segment is data or non-conforming code, THEN DPL must be >= CPL, or DPL must be >= RPL; OD;
In Protected Mode, the action of IRET depends on the setting of the nested task flag (NT) bit in the flag register. When popping the new flag image from the stack, the IOPL bits in the flag register are changed only when CPL equals 0.
If NT equals 0, IRET returns from an interrupt procedure without a task switch. The code returned to must be equally or less privileged than the interrupt routine (as indicated by the RPL bits of the CS selector popped from the stack). If the destination code is less privileged, IRET also pops the stack pointer and SS from the stack.
If NT equals 1, IRET reverses the operation of a CALL or INT that caused a task switch. The updated state of the task executing IRET is saved in its task state segment. If the task is reentered later, the code that follows IRET is executed.
up:
Chapter 17 -- 80386 Instruction Set
prev: INT/INTO Call to Interrupt Procedure
next: Jcc Jump if Condition is Met