Logo Search packages:      
Sourcecode: dosbox version File versions  Download package

flags.cpp

/*
 *  Copyright (C) 2002-2004  The DOSBox Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
      Lazy flag system was designed after the same kind of system used in Bochs.
      Probably still some bugs left in here.
*/

#include "dosbox.h"
#include "cpu.h"
#include "lazyflags.h"
#include "pic.h"

LazyFlags lflags;

/* CF     Carry Flag -- Set on high-order bit carry or borrow; cleared
          otherwise.
*/
Bitu get_CF(void) {

      switch (lflags.type) {
      case t_UNKNOWN:
      case t_INCb:
      case t_INCw:
      case t_INCd:
      case t_DECb:
      case t_DECw:
      case t_DECd:
      case t_MUL:
            return GETFLAG(CF);
            break;
      case t_ADDb:      
            return (lf_resb<lf_var1b);
      case t_ADDw:      
            return (lf_resw<lf_var1w);
      case t_ADDd:
            return (lf_resd<lf_var1d);
      case t_ADCb:
            return (lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b));
      case t_ADCw:
            return (lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w));
      case t_ADCd:
            return (lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d));
      case t_SBBb:
            return (lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff));
      case t_SBBw:
            return (lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff));
      case t_SBBd:
            return (lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff));
      case t_SUBb:
      case t_CMPb:
            return (lf_var1b<lf_var2b);
      case t_SUBw:
      case t_CMPw:
            return (lf_var1w<lf_var2w);
      case t_SUBd:
      case t_CMPd:
            return (lf_var1d<lf_var2d);
      case t_SHLb:
            if (lf_var2b>8) return false;
            else return (lf_var1b >> (8-lf_var2b)) & 1;
      case t_SHLw:
            if (lf_var2b>16) return false;
            else return (lf_var1w >> (16-lf_var2b)) & 1;
      case t_SHLd:
      case t_DSHLw:     /* Hmm this is not correct for shift higher than 16 */
      case t_DSHLd:
            return (lf_var1d >> (32 - lf_var2b)) & 1;
      case t_RCRb:
      case t_SHRb:
            return (lf_var1b >> (lf_var2b - 1)) & 1;
      case t_RCRw:
      case t_SHRw:
            return (lf_var1w >> (lf_var2b - 1)) & 1;
      case t_RCRd:
      case t_SHRd:
      case t_DSHRw:     /* Hmm this is not correct for shift higher than 16 */
      case t_DSHRd:
            return (lf_var1d >> (lf_var2b - 1)) & 1;
      case t_SARb:
            return (((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1;
      case t_SARw:
            return (((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1;
      case t_SARd:
            return (((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1;
      case t_NEGb:
            return lf_var1b;
      case t_NEGw:
            return lf_var1w;
      case t_NEGd:
            return lf_var1d;
      case t_ORb:
      case t_ORw:
      case t_ORd:
      case t_ANDb:
      case t_ANDw:
      case t_ANDd:
      case t_XORb:
      case t_XORw:
      case t_XORd:
      case t_TESTb:
      case t_TESTw:
      case t_TESTd:
            return false;     /* Set to false */
      case t_DIV:
            return false;     /* Unkown */
      default:
            LOG(LOG_CPU,LOG_ERROR)("get_CF Unknown %d",lflags.type);
      }
      return 0;
}

/* AF     Adjust flag -- Set on carry from or borrow to the low order
            four bits of   AL; cleared otherwise. Used for decimal
            arithmetic.
*/
Bitu get_AF(void) {
      Bitu type=lflags.type;
      switch (type) {
      case t_UNKNOWN:
            return GETFLAG(AF);
      case t_ADDb:      
      case t_ADCb:
      case t_SBBb:
      case t_SUBb:
      case t_CMPb:
            return ((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10;
      case t_ADDw:
      case t_ADCw:
      case t_SBBw:
      case t_SUBw:
      case t_CMPw:
            return ((lf_var1w ^ lf_var2w) ^ lf_resw) & 0x10;
      case t_ADCd:
      case t_ADDd:
      case t_SBBd:
      case t_SUBd:
      case t_CMPd:
            return ((lf_var1d ^ lf_var2d) ^ lf_resd) & 0x10;
      case t_INCb:
            return (lf_resb & 0x0f) == 0;
      case t_INCw:
            return (lf_resw & 0x0f) == 0;
      case t_INCd:
            return (lf_resd & 0x0f) == 0;
      case t_DECb:
            return (lf_resb & 0x0f) == 0x0f;
      case t_DECw:
            return (lf_resw & 0x0f) == 0x0f;
      case t_DECd:
            return (lf_resd & 0x0f) == 0x0f;
      case t_NEGb:
            return lf_var1b & 0x0f;
      case t_NEGw:
            return lf_var1w & 0x0f;
      case t_NEGd:
            return lf_var1d & 0x0f;
      case t_ORb:
      case t_ORw:
      case t_ORd:
      case t_ANDb:
      case t_ANDw:
      case t_ANDd:
      case t_XORb:
      case t_XORw:
      case t_XORd:
      case t_TESTb:
      case t_TESTw:
      case t_TESTd:
      case t_SHLb:
      case t_SHLw:
      case t_SHLd:
      case t_SHRb:
      case t_SHRw:
      case t_SHRd:
      case t_SARb:
      case t_SARw:
      case t_SARd:
      case t_DSHLw:
      case t_DSHLd:
      case t_DSHRw:
      case t_DSHRd:
      case t_DIV:
      case t_MUL:
            return false;                           /* Unkown */
      default:
            LOG(LOG_CPU,LOG_ERROR)("get_AF Unknown %d",lflags.type);
      }
      return 0;
}

/* ZF     Zero Flag -- Set if result is zero; cleared otherwise.
*/

Bitu get_ZF(void) {
      Bitu type=lflags.type;
      switch (type) {
      case t_UNKNOWN:
            return GETFLAG(ZF);
      case t_ADDb:      
      case t_ORb:
      case t_ADCb:
      case t_SBBb:
      case t_ANDb:
      case t_XORb:
      case t_SUBb:
      case t_CMPb:
      case t_INCb:
      case t_DECb:
      case t_TESTb:
      case t_SHLb:
      case t_SHRb:
      case t_SARb:
      case t_NEGb:
            return (lf_resb==0);
      case t_ADDw:      
      case t_ORw:
      case t_ADCw:
      case t_SBBw:
      case t_ANDw:
      case t_XORw:
      case t_SUBw:
      case t_CMPw:
      case t_INCw:
      case t_DECw:
      case t_TESTw:
      case t_SHLw:
      case t_SHRw:
      case t_SARw:
      case t_DSHLw:
      case t_DSHRw:
      case t_NEGw:
            return (lf_resw==0);
      case t_ADDd:
      case t_ORd:
      case t_ADCd:
      case t_SBBd:
      case t_ANDd:
      case t_XORd:
      case t_SUBd:
      case t_CMPd:
      case t_INCd:
      case t_DECd:
      case t_TESTd:
      case t_SHLd:
      case t_SHRd:
      case t_SARd:
      case t_DSHLd:
      case t_DSHRd:
      case t_NEGd:
            return (lf_resd==0);
      case t_DIV:
      case t_MUL:
            return false;           /* Unkown */
      default:
            LOG(LOG_CPU,LOG_ERROR)("get_ZF Unknown %d",lflags.type);
      }
      return false;
}
/* SF     Sign Flag -- Set equal to high-order bit of result (0 is
            positive, 1 if negative).
*/
Bitu get_SF(void) {
      Bitu type=lflags.type;
      switch (type) {
      case t_UNKNOWN:
            return GETFLAG(SF);
      case t_ADDb:
      case t_ORb:
      case t_ADCb:
      case t_SBBb:
      case t_ANDb:
      case t_XORb:
      case t_SUBb:
      case t_CMPb:
      case t_INCb:
      case t_DECb:
      case t_TESTb:
      case t_SHLb:
      case t_SHRb:
      case t_SARb:
      case t_NEGb:
            return      (lf_resb&0x80);
      case t_ADDw:
      case t_ORw:
      case t_ADCw:
      case t_SBBw:
      case t_ANDw:
      case t_XORw:
      case t_SUBw:
      case t_CMPw:
      case t_INCw:
      case t_DECw:
      case t_TESTw:
      case t_SHLw:
      case t_SHRw:
      case t_SARw:
      case t_DSHLw:
      case t_DSHRw:
      case t_NEGw:
            return      (lf_resw&0x8000);
      case t_ADDd:
      case t_ORd:
      case t_ADCd:
      case t_SBBd:
      case t_ANDd:
      case t_XORd:
      case t_SUBd:
      case t_CMPd:
      case t_INCd:
      case t_DECd:
      case t_TESTd:
      case t_SHLd:
      case t_SHRd:
      case t_SARd:
      case t_DSHLd:
      case t_DSHRd:
      case t_NEGd:
            return      (lf_resd&0x80000000);
      case t_DIV:
      case t_MUL:
            return false;     /* Unkown */
      default:
            LOG(LOG_CPU,LOG_ERROR)("get_SF Unkown %d",lflags.type);
      }
      return false;

}
Bitu get_OF(void) {
      Bitu type=lflags.type;
      switch (type) {
      case t_UNKNOWN:
      case t_MUL:
            return GETFLAG(OF);
      case t_ADDb:
      case t_ADCb:
            return ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var2b)) & 0x80;
      case t_ADDw:
      case t_ADCw:
            return ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var2w)) & 0x8000;
      case t_ADDd:
      case t_ADCd:
            return ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var2d)) & 0x80000000;
      case t_SBBb:
      case t_SUBb:
      case t_CMPb:
            return ((lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb)) & 0x80;
      case t_SBBw:
      case t_SUBw:
      case t_CMPw:
            return ((lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw)) & 0x8000;
      case t_SBBd:
      case t_SUBd:
      case t_CMPd:
            return ((lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd)) & 0x80000000;
      case t_INCb:
            return (lf_resb == 0x80);
      case t_INCw:
            return (lf_resw == 0x8000);
      case t_INCd:
            return (lf_resd == 0x80000000);
      case t_DECb:
            return (lf_resb == 0x7f);
      case t_DECw:
            return (lf_resw == 0x7fff);
      case t_DECd:
            return (lf_resd == 0x7fffffff);
      case t_NEGb:
            return (lf_var1b == 0x80);
      case t_NEGw:
            return (lf_var1w == 0x8000);
      case t_NEGd:
            return (lf_var1d == 0x80000000);
      case t_SHLb:
      case t_SHRb:
            return (lf_resb ^ lf_var1b) & 0x80;
      case t_SHLw:
      case t_SHRw:
      case t_DSHRw:
      case t_DSHLw:
            return (lf_resw ^ lf_var1w) & 0x8000;
      case t_SHLd:
      case t_SHRd:
      case t_DSHRd:
      case t_DSHLd:
            return (lf_resd ^ lf_var1d) & 0x80000000;
      case t_ORb:
      case t_ORw:
      case t_ORd:
      case t_ANDb:
      case t_ANDw:
      case t_ANDd:
      case t_XORb:
      case t_XORw:
      case t_XORd:
      case t_TESTb:
      case t_TESTw:
      case t_TESTd:
      case t_SARb:
      case t_SARw:
      case t_SARd:
            return false;                 /* Return false */
      case t_DIV:
            return false;           /* Unkown */
      default:
            LOG(LOG_CPU,LOG_ERROR)("get_OF Unkown %d",lflags.type);
      }
      return false;
}

Bit16u parity_lookup[256] = {
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF
  };

Bitu get_PF(void) {
      switch (lflags.type) {
      case t_UNKNOWN:
            return GETFLAG(PF);
      default:
            return      (parity_lookup[lf_resb]);;
      };
      return false;
}


#if 0

Bitu FillFlags(void) {
//    if (lflags.type==t_UNKNOWN) return reg_flags;
      Bitu new_word=(reg_flags & ~FLAG_MASK);
      if (get_CF()) new_word|=FLAG_CF;
      if (get_PF()) new_word|=FLAG_PF;
      if (get_AF()) new_word|=FLAG_AF;
      if (get_ZF()) new_word|=FLAG_ZF;
      if (get_SF()) new_word|=FLAG_SF;
      if (get_OF()) new_word|=FLAG_OF;
      reg_flags=new_word;
      lflags.type=t_UNKNOWN;
      return reg_flags;
}

#else

#define DOFLAG_PF reg_flags=(reg_flags & ~FLAG_PF) | parity_lookup[lf_resb];

#define DOFLAG_AF reg_flags=(reg_flags & ~FLAG_AF) | (((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10);

#define DOFLAG_ZFb      SETFLAGBIT(ZF,lf_resb==0);
#define DOFLAG_ZFw      SETFLAGBIT(ZF,lf_resw==0);
#define DOFLAG_ZFd      SETFLAGBIT(ZF,lf_resd==0);

#define DOFLAG_SFb      reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resb & 0x80) >> 0);
#define DOFLAG_SFw      reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resw & 0x8000) >> 8);
#define DOFLAG_SFd      reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resd & 0x80000000) >> 24);

#define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT);

#define SET_FLAG SETFLAGBIT
Bitu FillFlags(void) {
      switch (lflags.type) {
      case t_UNKNOWN:
            break;
      case t_ADDb:      
            SET_FLAG(CF,(lf_resb<lf_var1b));
            DOFLAG_AF;
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80);
            DOFLAG_PF;
            break;
      case t_ADDw:      
            SET_FLAG(CF,(lf_resw<lf_var1w));
            DOFLAG_AF;
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000);
            DOFLAG_PF;
            break;
      case t_ADDd:
            SET_FLAG(CF,(lf_resd<lf_var1d));
            DOFLAG_AF;
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000);
            DOFLAG_PF;
            break;
      case t_ADCb:
            SET_FLAG(CF,(lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b)));
            DOFLAG_AF;
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80);
            DOFLAG_PF;
            break;
      case t_ADCw:
            SET_FLAG(CF,(lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w)));
            DOFLAG_AF;
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000);
            DOFLAG_PF;
            break;
      case t_ADCd:
            SET_FLAG(CF,(lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d)));
            DOFLAG_AF;
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000);
            DOFLAG_PF;
            break;


      case t_SBBb:
            SET_FLAG(CF,(lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff)));
            DOFLAG_AF;
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80);
            DOFLAG_PF;
            break;
      case t_SBBw:
            SET_FLAG(CF,(lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff)));
            DOFLAG_AF;
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000);
            DOFLAG_PF;
            break;
      case t_SBBd:
            SET_FLAG(CF,(lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff)));
            DOFLAG_AF;
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000);
            DOFLAG_PF;
            break;
      

      case t_SUBb:
      case t_CMPb:
            SET_FLAG(CF,(lf_var1b<lf_var2b));
            DOFLAG_AF;
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80);
            DOFLAG_PF;
            break;
      case t_SUBw:
      case t_CMPw:
            SET_FLAG(CF,(lf_var1w<lf_var2w));
            DOFLAG_AF;
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000);
            DOFLAG_PF;
            break;
      case t_SUBd:
      case t_CMPd:
            SET_FLAG(CF,(lf_var1d<lf_var2d));
            DOFLAG_AF;
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000);
            DOFLAG_PF;
            break;


      case t_ORb:
            SET_FLAG(CF,false);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_ORw:
            SET_FLAG(CF,false);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_ORd:
            SET_FLAG(CF,false);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      
      
      case t_TESTb:
      case t_ANDb:
            SET_FLAG(CF,false);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_TESTw:
      case t_ANDw:
            SET_FLAG(CF,false);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_TESTd:
      case t_ANDd:
            SET_FLAG(CF,false);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;

      
      case t_XORb:
            SET_FLAG(CF,false);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_XORw:
            SET_FLAG(CF,false);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_XORd:
            SET_FLAG(CF,false);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;


      case t_SHLb:
            if (lf_var2b>8) SET_FLAG(CF,false);
            else SET_FLAG(CF,(lf_var1b >> (8-lf_var2b)) & 1);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80);
            DOFLAG_PF;
            break;
      case t_SHLw:
            if (lf_var2b>16) SET_FLAG(CF,false);
            else SET_FLAG(CF,(lf_var1w >> (16-lf_var2b)) & 1);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
            DOFLAG_PF;
            break;
      case t_SHLd:
            SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
            DOFLAG_PF;
            break;


      case t_DSHLw:
            SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
            DOFLAG_PF;
            break;
      case t_DSHLd:
            SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
            DOFLAG_PF;
            break;


      case t_SHRb:
            SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80);
            DOFLAG_PF;
            break;
      case t_SHRw:
            SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
            DOFLAG_PF;
            break;
      case t_SHRd:
            SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
            DOFLAG_PF;
            break;

      
      case t_DSHRw:     /* Hmm this is not correct for shift higher than 16 */
            SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
            DOFLAG_PF;
            break;
      case t_DSHRd:
            SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
            DOFLAG_PF;
            break;


      case t_SARb:
            SET_FLAG(CF,(((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_SARw:
            SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;
      case t_SARd:
            SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,false);
            DOFLAG_PF;
            break;

      case t_INCb:
            SET_FLAG(AF,(lf_resb & 0x0f) == 0);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_resb == 0x80));
            DOFLAG_PF;
            break;
      case t_INCw:
            SET_FLAG(AF,(lf_resw & 0x0f) == 0);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_resw == 0x8000));
            DOFLAG_PF;
            break;
      case t_INCd:
            SET_FLAG(AF,(lf_resd & 0x0f) == 0);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_resd == 0x80000000));
            DOFLAG_PF;
            break;

      case t_DECb:
            SET_FLAG(AF,(lf_resb & 0x0f) == 0);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_resb == 0x7f));
            DOFLAG_PF;
            break;
      case t_DECw:
            SET_FLAG(AF,(lf_resw & 0x0f) == 0);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_resw == 0x7fff));
            DOFLAG_PF;
            break;
      case t_DECd:
            SET_FLAG(AF,(lf_resd & 0x0f) == 0);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_resd == 0x7fffffff));
            DOFLAG_PF;
            break;

      case t_NEGb:
            SET_FLAG(CF,(lf_var1b!=0));
            SET_FLAG(AF,(lf_resb & 0x0f) == 0);
            DOFLAG_ZFb;
            DOFLAG_SFb;
            SET_FLAG(OF,(lf_var1b == 0x80));
            DOFLAG_PF;
            break;
      case t_NEGw:
            SET_FLAG(CF,(lf_var1w!=0));
            SET_FLAG(AF,(lf_resw & 0x0f) == 0);
            DOFLAG_ZFw;
            DOFLAG_SFw;
            SET_FLAG(OF,(lf_var1w == 0x8000));
            DOFLAG_PF;
            break;
      case t_NEGd:
            SET_FLAG(CF,(lf_var1d!=0));
            SET_FLAG(AF,(lf_resd & 0x0f) == 0);
            DOFLAG_ZFd;
            DOFLAG_SFd;
            SET_FLAG(OF,(lf_var1d == 0x80000000));
            DOFLAG_PF;
            break;

      
      case t_DIV:
      case t_MUL:
            break;

      default:
            LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type);
            return 0;
      }
      lflags.type=t_UNKNOWN;
      return reg_flags;
}

#endif

Generated by  Doxygen 1.6.0   Back to index