core/x86/interp.c
/* Arithmetic eflags analysis to see if sequence of instrs reads an
 * arithmetic flag prior to writing it.
 * Usage: first initialize status to 0 and eflags_6 to 0.
 * Then call this routine for each instr in sequence, assigning result to status.
 * eflags_6 holds flags written and read so far.
 * Uses these flags, defined in instr.h, as status values:
 *   EFLAGS_WRITE_6   = writes all 6 flags before reading any
 *   EFLAGS_WRITE_OF  = writes OF before reading it
 *   EFLAGS_READ_6    = reads some of 6 before writing
 *   EFLAGS_READ_OF   = reads OF before writing OF
 *   0                = no information yet
 */
Arithmetic eflags analysis to see if sequence of instrs reads an
arithmetic flag prior to writing it.
Usage: first initialize status to 0 and eflags_6 to 0.
Then call this routine for each instr in sequence, assigning result to status.
eflags_6 holds flags written and read so far.
Arithmetic eflags analysis to see if sequence of instrs reads an arithmetic flag prior to writing it . Usage : first initialize status to 0 and eflags_6 to 0 . Then call this routine for each instr in sequence assigning result to status . eflags_6 holds flags written and read so far .
static inline int
eflags_analysis(instr_t *instr, int status, uint *eflags_6)
{
    uint e6 = *eflags_6; 
    uint e6_w2r = EFLAGS_WRITE_TO_READ(e6);
    uint instr_eflags = instr_get_arith_flags(instr);
    if (instr_eflags == 0 || status == EFLAGS_READ_OF || status == EFLAGS_WRITE_6)
        return status;
    if ((instr_eflags & EFLAGS_READ_6) != 0 &&
        (!instr_opcode_valid(instr) || !instr_is_interrupt(instr))) {
        e6 |= (instr_eflags & EFLAGS_READ_6);
        *eflags_6 = e6;
        if ((e6_w2r | (instr_eflags & EFLAGS_READ_6)) != e6_w2r) {
            status = EFLAGS_READ_6; 
            LOG(THREAD_GET, LOG_INTERP, 4, "\treads flag before writing it!\n");
            if ((instr_eflags & EFLAGS_READ_OF) != 0 && (e6 & EFLAGS_WRITE_OF) == 0) {
                status = EFLAGS_READ_OF; 
                LOG(THREAD_GET, LOG_INTERP, 4, "\t  reads OF prior to writing it!\n");
            }
        }
    } else if ((instr_eflags & EFLAGS_WRITE_6) != 0) {
        e6 |= (instr_eflags & EFLAGS_WRITE_6);
        *eflags_6 = e6;
        if ((e6 & EFLAGS_WRITE_6) == EFLAGS_WRITE_6 && (e6 & EFLAGS_READ_6) == 0) {
            status = EFLAGS_WRITE_6; 
            LOG(THREAD_GET, LOG_INTERP, 4, "\twrote all 6 flags now!\n");
        }
        else if ((e6 & EFLAGS_WRITE_OF) != 0 && (e6 & EFLAGS_READ_OF) == 0) {
            status = EFLAGS_WRITE_OF; 
            LOG(THREAD_GET, LOG_INTERP, 4, "\twrote overflow flag before reading it!\n");
        }
    }
    return status;
}
static inline int eflags_analysis ( instr_t * instr , int status , uint * eflags_6 ) { uint e6 = * eflags_6 ; uint e6_w2r = EFLAGS_WRITE_TO_READ ( e6 ) ; uint instr_eflags = instr_get_arith_flags ( instr ) ; if ( instr_eflags == 0 || status == EFLAGS_READ_OF || status == EFLAGS_WRITE_6 ) return status ; if ( ( instr_eflags & EFLAGS_READ_6 ) != 0 && ( ! instr_opcode_valid ( instr ) || ! instr_is_interrupt ( instr ) ) ) { e6 |= ( instr_eflags & EFLAGS_READ_6 ) ; * eflags_6 = e6 ; if ( ( e6_w2r | ( instr_eflags & EFLAGS_READ_6 ) ) != e6_w2r ) { status = EFLAGS_READ_6 ; LOG ( THREAD_GET , LOG_INTERP , 4 , " \t \n " ) ; if ( ( instr_eflags & EFLAGS_READ_OF ) != 0 && ( e6 & EFLAGS_WRITE_OF ) == 0 ) { status = EFLAGS_READ_OF ; LOG ( THREAD_GET , LOG_INTERP , 4 , " \t \n " ) ; } } } else if ( ( instr_eflags & EFLAGS_WRITE_6 ) != 0 ) { e6 |= ( instr_eflags & EFLAGS_WRITE_6 ) ; * eflags_6 = e6 ; if ( ( e6 & EFLAGS_WRITE_6 ) == EFLAGS_WRITE_6 && ( e6 & EFLAGS_READ_6 ) == 0 ) { status = EFLAGS_WRITE_6 ; LOG ( THREAD_GET , LOG_INTERP , 4 , " \t \n " ) ; } else if ( ( e6 & EFLAGS_WRITE_OF ) != 0 && ( e6 & EFLAGS_READ_OF ) == 0 ) { status = EFLAGS_WRITE_OF ; LOG ( THREAD_GET , LOG_INTERP , 4 , " \t \n " ) ; } } return status ; }
Arithmetic eflags analysis to see if sequence of instrs reads an
 arithmetic flag prior to writing it.
Arithmetic eflags analysis to see if sequence of instrs reads an arithmetic flag prior to writing it .
/* local copy */ /* Keep going until result is non-zero, also keep going if
     * result is writes to OF to see if later writes to rest of flags
     * before reading any, and keep going if reads one of the 6 to see
     * if later writes to OF before reading it.
     */ /* we ignore interrupts */ /* store the flags we're reading */ /* we're reading a flag that has not been written yet */ /* some read before all written */ /* reads OF before writing! */ /* store the flags we're writing */ /* check if all written but none read yet */ /* all written before read */ /* check if at least OF was written but not read */ /* OF written before read */