2009-05-02 23:03:37 +02:00
|
|
|
/*
|
2009-05-03 00:28:34 +02:00
|
|
|
* Copyright (C) 2002-2007 The DOSBox Team
|
2009-05-02 23:03:37 +02:00
|
|
|
*
|
|
|
|
* 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
|
2009-05-03 00:02:15 +02:00
|
|
|
* GNU General Public License for more details.
|
2009-05-02 23:03:37 +02:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Jumps */
|
|
|
|
|
2009-05-03 00:28:34 +02:00
|
|
|
/* All Byte general instructions */
|
2009-05-02 23:03:37 +02:00
|
|
|
#define ADDB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b+lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_ADDb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ADCB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.oldcf=get_CF()!=0; \
|
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b+lf_var2b+lflags.oldcf; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_ADCb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SBBB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.oldcf=get_CF()!=0; \
|
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b-(lf_var2b+lflags.oldcf); \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_SBBb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SUBB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b-lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_SUBb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ORB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b | lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_ORb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define XORB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b ^ lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_XORb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ANDB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b & lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_ANDb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define CMPB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b-lf_var2b; \
|
|
|
|
lflags.type=t_CMPb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define TESTB(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b & lf_var2b; \
|
|
|
|
lflags.type=t_TESTb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
/* All Word General instructions */
|
|
|
|
|
|
|
|
#define ADDW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w+lf_var2w; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_ADDw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ADCW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.oldcf=get_CF()!=0; \
|
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w+lf_var2w+lflags.oldcf; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_ADCw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SBBW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.oldcf=get_CF()!=0; \
|
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w-(lf_var2w+lflags.oldcf); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_SBBw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SUBW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w-lf_var2w; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_SUBw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ORW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w | lf_var2w; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_ORw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define XORW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w ^ lf_var2w; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_XORw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ANDW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w & lf_var2w; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_ANDw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define CMPW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w-lf_var2w; \
|
|
|
|
lflags.type=t_CMPw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define TESTW(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2w=op2; \
|
|
|
|
lf_resw=lf_var1w & lf_var2w; \
|
|
|
|
lflags.type=t_TESTw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
/* All DWORD General Instructions */
|
|
|
|
|
|
|
|
#define ADDD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d+lf_var2d; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_ADDd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ADCD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.oldcf=get_CF()!=0; \
|
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d+lf_var2d+lflags.oldcf; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_ADCd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SBBD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.oldcf=get_CF()!=0; \
|
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_SBBd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SUBD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d-lf_var2d; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_SUBd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ORD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d | lf_var2d; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_ORd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define XORD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d ^ lf_var2d; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_XORd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define ANDD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d & lf_var2d; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_ANDd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define CMPD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d-lf_var2d; \
|
|
|
|
lflags.type=t_CMPd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
#define TESTD(op1,op2,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2d=op2; \
|
|
|
|
lf_resd=lf_var1d & lf_var2d; \
|
|
|
|
lflags.type=t_TESTd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define INCB(op1,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
LoadCF;lf_var1b=load(op1); \
|
|
|
|
lf_resb=lf_var1b+1; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_INCb; \
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define INCW(op1,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
LoadCF;lf_var1w=load(op1); \
|
|
|
|
lf_resw=lf_var1w+1; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_INCw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define INCD(op1,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
LoadCF;lf_var1d=load(op1); \
|
|
|
|
lf_resd=lf_var1d+1; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_INCd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define DECB(op1,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
LoadCF;lf_var1b=load(op1); \
|
|
|
|
lf_resb=lf_var1b-1; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_DECb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define DECW(op1,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
LoadCF;lf_var1w=load(op1); \
|
|
|
|
lf_resw=lf_var1w-1; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_DECw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define DECD(op1,load,save) \
|
2009-05-02 23:53:27 +02:00
|
|
|
LoadCF;lf_var1d=load(op1); \
|
|
|
|
lf_resd=lf_var1d-1; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_DECd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-03 00:08:43 +02:00
|
|
|
#define ROLB(op1,op2,load,save) \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (!(op2&0x7)) { \
|
|
|
|
if (op2&0x18) { \
|
|
|
|
FillFlags(); \
|
|
|
|
SETFLAGBIT(CF,op1 & 1); \
|
|
|
|
SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); \
|
|
|
|
} \
|
|
|
|
break; \
|
|
|
|
} \
|
2009-05-03 00:08:43 +02:00
|
|
|
FillFlags(); \
|
|
|
|
lf_var1b=load(op1); \
|
|
|
|
lf_var2b=op2&0x07; \
|
|
|
|
lf_resb=(lf_var1b << lf_var2b) | \
|
|
|
|
(lf_var1b >> (8-lf_var2b)); \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
SETFLAGBIT(CF,lf_resb & 1); \
|
|
|
|
SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7));
|
|
|
|
|
|
|
|
#define ROLW(op1,op2,load,save) \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (!(op2&0xf)) { \
|
|
|
|
if (op2&0x10) { \
|
|
|
|
FillFlags(); \
|
|
|
|
SETFLAGBIT(CF,op1 & 1); \
|
|
|
|
} \
|
|
|
|
break; \
|
|
|
|
} \
|
2009-05-03 00:08:43 +02:00
|
|
|
FillFlags(); \
|
|
|
|
lf_var1w=load(op1); \
|
|
|
|
lf_var2b=op2&0xf; \
|
|
|
|
lf_resw=(lf_var1w << lf_var2b) | \
|
|
|
|
(lf_var1w >> (16-lf_var2b)); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
SETFLAGBIT(CF,lf_resw & 1); \
|
|
|
|
SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15));
|
|
|
|
|
|
|
|
#define ROLD(op1,op2,load,save) \
|
|
|
|
if (!op2) break; \
|
|
|
|
FillFlags(); \
|
|
|
|
lf_var1d=load(op1); \
|
|
|
|
lf_var2b=op2; \
|
|
|
|
lf_resd=(lf_var1d << lf_var2b) | \
|
|
|
|
(lf_var1d >> (32-lf_var2b)); \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
SETFLAGBIT(CF,lf_resd & 1); \
|
|
|
|
SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31));
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-03 00:08:43 +02:00
|
|
|
#define RORB(op1,op2,load,save) \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (!(op2&0x7)) { \
|
|
|
|
if (op2&0x10) { \
|
|
|
|
FillFlags(); \
|
|
|
|
SETFLAGBIT(CF,op1>>7); \
|
|
|
|
SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); \
|
|
|
|
} \
|
|
|
|
break; \
|
|
|
|
} \
|
2009-05-03 00:08:43 +02:00
|
|
|
FillFlags(); \
|
|
|
|
lf_var1b=load(op1); \
|
|
|
|
lf_var2b=op2&0x07; \
|
|
|
|
lf_resb=(lf_var1b >> lf_var2b) | \
|
|
|
|
(lf_var1b << (8-lf_var2b)); \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
SETFLAGBIT(CF,lf_resb & 0x80); \
|
|
|
|
if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80);
|
|
|
|
|
|
|
|
#define RORW(op1,op2,load,save) \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (!(op2&0xf)) { \
|
|
|
|
if (op2&0x10) { \
|
|
|
|
FillFlags(); \
|
|
|
|
SETFLAGBIT(CF,op1>>15); \
|
|
|
|
} \
|
|
|
|
break; \
|
|
|
|
} \
|
2009-05-03 00:08:43 +02:00
|
|
|
FillFlags(); \
|
|
|
|
lf_var1w=load(op1); \
|
|
|
|
lf_var2b=op2&0xf; \
|
|
|
|
lf_resw=(lf_var1w >> lf_var2b) | \
|
|
|
|
(lf_var1w << (16-lf_var2b)); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
SETFLAGBIT(CF,lf_resw & 0x8000); \
|
|
|
|
if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000);
|
|
|
|
|
|
|
|
#define RORD(op1,op2,load,save) \
|
|
|
|
if (!op2) break; \
|
|
|
|
FillFlags(); \
|
|
|
|
lf_var1d=load(op1); \
|
|
|
|
lf_var2b=op2; \
|
|
|
|
lf_resd=(lf_var1d >> lf_var2b) | \
|
|
|
|
(lf_var1d << (32-lf_var2b)); \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
SETFLAGBIT(CF,lf_resd & 0x80000000); \
|
|
|
|
if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000);
|
|
|
|
|
|
|
|
|
|
|
|
#define RCLB(op1,op2,load,save) \
|
|
|
|
if (!(op2%9)) break; \
|
|
|
|
{ Bit8u cf=(Bit8u)FillFlags()&0x1; \
|
|
|
|
lf_var1b=load(op1); \
|
|
|
|
lf_var2b=op2%9; \
|
|
|
|
lf_resb=(lf_var1b << lf_var2b) | \
|
2009-05-02 23:53:27 +02:00
|
|
|
(cf << (lf_var2b-1)) | \
|
2009-05-03 00:08:43 +02:00
|
|
|
(lf_var1b >> (9-lf_var2b)); \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); \
|
|
|
|
SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define RCLW(op1,op2,load,save) \
|
|
|
|
if (!(op2%17)) break; \
|
|
|
|
{ Bit16u cf=(Bit16u)FillFlags()&0x1; \
|
|
|
|
lf_var1w=load(op1); \
|
|
|
|
lf_var2b=op2%17; \
|
|
|
|
lf_resw=(lf_var1w << lf_var2b) | \
|
|
|
|
(cf << (lf_var2b-1)) | \
|
|
|
|
(lf_var1w >> (17-lf_var2b)); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); \
|
|
|
|
SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define RCLD(op1,op2,load,save) \
|
|
|
|
if (!op2) break; \
|
|
|
|
{ Bit32u cf=(Bit32u)FillFlags()&0x1; \
|
|
|
|
lf_var1d=load(op1); \
|
|
|
|
lf_var2b=op2; \
|
|
|
|
if (lf_var2b==1) { \
|
|
|
|
lf_resd=(lf_var1d << 1) | cf; \
|
|
|
|
} else { \
|
|
|
|
lf_resd=(lf_var1d << lf_var2b) | \
|
|
|
|
(cf << (lf_var2b-1)) | \
|
|
|
|
(lf_var1d >> (33-lf_var2b)); \
|
|
|
|
} \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1)); \
|
|
|
|
SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define RCRB(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (op2%9) { \
|
2009-05-02 23:53:27 +02:00
|
|
|
Bit8u cf=(Bit8u)FillFlags()&0x1; \
|
2009-05-03 00:08:43 +02:00
|
|
|
lf_var1b=load(op1); \
|
|
|
|
lf_var2b=op2%9; \
|
|
|
|
lf_resb=(lf_var1b >> lf_var2b) | \
|
|
|
|
(cf << (8-lf_var2b)) | \
|
|
|
|
(lf_var1b << (9-lf_var2b)); \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); \
|
|
|
|
SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define RCRW(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (op2%17) { \
|
2009-05-02 23:53:27 +02:00
|
|
|
Bit16u cf=(Bit16u)FillFlags()&0x1; \
|
2009-05-03 00:08:43 +02:00
|
|
|
lf_var1w=load(op1); \
|
|
|
|
lf_var2b=op2%17; \
|
|
|
|
lf_resw=(lf_var1w >> lf_var2b) | \
|
|
|
|
(cf << (16-lf_var2b)) | \
|
|
|
|
(lf_var1w << (17-lf_var2b)); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); \
|
|
|
|
SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define RCRD(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (op2) { \
|
2009-05-02 23:53:27 +02:00
|
|
|
Bit32u cf=(Bit32u)FillFlags()&0x1; \
|
2009-05-03 00:08:43 +02:00
|
|
|
lf_var1d=load(op1); \
|
|
|
|
lf_var2b=op2; \
|
|
|
|
if (lf_var2b==1) { \
|
|
|
|
lf_resd=lf_var1d >> 1 | cf << 31; \
|
2009-05-02 23:43:00 +02:00
|
|
|
} else { \
|
2009-05-03 00:08:43 +02:00
|
|
|
lf_resd=(lf_var1d >> lf_var2b) | \
|
|
|
|
(cf << (32-lf_var2b)) | \
|
|
|
|
(lf_var1d << (33-lf_var2b)); \
|
2009-05-02 23:43:00 +02:00
|
|
|
} \
|
2009-05-03 00:08:43 +02:00
|
|
|
save(op1,lf_resd); \
|
|
|
|
SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); \
|
|
|
|
SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
#define SHLB(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b << lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_SHLb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SHLW(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2b=op2 ; \
|
|
|
|
lf_resw=lf_var1w << lf_var2b; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_SHLw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SHLD(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resd=lf_var1d << lf_var2b; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_SHLd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
#define SHRB(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resb=lf_var1b >> lf_var2b; \
|
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_SHRb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SHRW(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resw=lf_var1w >> lf_var2b; \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_SHRw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SHRD(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1d=load(op1);lf_var2b=op2; \
|
|
|
|
lf_resd=lf_var1d >> lf_var2b; \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_SHRd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
#define SARB(op1,op2,load,save) \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1b=load(op1);lf_var2b=op2; \
|
|
|
|
if (lf_var2b>8) lf_var2b=8; \
|
|
|
|
if (lf_var1b & 0x80) { \
|
|
|
|
lf_resb=(lf_var1b >> lf_var2b)| \
|
|
|
|
(0xff << (8 - lf_var2b)); \
|
2009-05-02 23:03:37 +02:00
|
|
|
} else { \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_resb=lf_var1b >> lf_var2b; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
2009-05-02 23:53:27 +02:00
|
|
|
save(op1,lf_resb); \
|
|
|
|
lflags.type=t_SARb;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SARW(op1,op2,load,save) \
|
2009-05-02 23:12:18 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var1w=load(op1);lf_var2b=op2; \
|
|
|
|
if (lf_var2b>16) lf_var2b=16; \
|
|
|
|
if (lf_var1w & 0x8000) { \
|
|
|
|
lf_resw=(lf_var1w >> lf_var2b)| \
|
|
|
|
(0xffff << (16 - lf_var2b)); \
|
2009-05-02 23:03:37 +02:00
|
|
|
} else { \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_resw=lf_var1w >> lf_var2b; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
2009-05-02 23:53:27 +02:00
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_SARw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#define SARD(op1,op2,load,save) \
|
2009-05-02 23:12:18 +02:00
|
|
|
if (!op2) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var2b=op2;lf_var1d=load(op1); \
|
|
|
|
if (lf_var1d & 0x80000000) { \
|
|
|
|
lf_resd=(lf_var1d >> lf_var2b)| \
|
|
|
|
(0xffffffff << (32 - lf_var2b)); \
|
2009-05-02 23:03:37 +02:00
|
|
|
} else { \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_resd=lf_var1d >> lf_var2b; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
2009-05-02 23:53:27 +02:00
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_SARd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2009-05-02 23:43:00 +02:00
|
|
|
#define DAA() \
|
|
|
|
if (((reg_al & 0x0F)>0x09) || get_AF()) { \
|
2009-05-03 00:28:34 +02:00
|
|
|
if ((reg_al > 0x99) || get_CF()) { \
|
|
|
|
reg_al+=0x60; \
|
|
|
|
SETFLAGBIT(CF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false); \
|
|
|
|
} \
|
2009-05-02 23:43:00 +02:00
|
|
|
reg_al+=0x06; \
|
|
|
|
SETFLAGBIT(AF,true); \
|
|
|
|
} else { \
|
2009-05-03 00:28:34 +02:00
|
|
|
if ((reg_al > 0x99) || get_CF()) { \
|
|
|
|
reg_al+=0x60; \
|
|
|
|
SETFLAGBIT(CF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false); \
|
|
|
|
} \
|
2009-05-02 23:43:00 +02:00
|
|
|
SETFLAGBIT(AF,false); \
|
|
|
|
} \
|
|
|
|
SETFLAGBIT(SF,(reg_al&0x80)); \
|
|
|
|
SETFLAGBIT(ZF,(reg_al==0)); \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(PF,parity_lookup[reg_al]); \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.type=t_UNKNOWN;
|
2009-05-02 23:43:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
#define DAS() \
|
|
|
|
if (((reg_al & 0x0f) > 9) || get_AF()) { \
|
2009-05-03 00:28:34 +02:00
|
|
|
if ((reg_al>0x99) || get_CF()) { \
|
|
|
|
reg_al-=0x60; \
|
|
|
|
SETFLAGBIT(CF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false); \
|
|
|
|
} \
|
2009-05-02 23:43:00 +02:00
|
|
|
reg_al-=6; \
|
|
|
|
SETFLAGBIT(AF,true); \
|
|
|
|
} else { \
|
2009-05-03 00:28:34 +02:00
|
|
|
if ((reg_al>0x99) || get_CF()) { \
|
|
|
|
reg_al-=0x60; \
|
|
|
|
SETFLAGBIT(CF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false); \
|
|
|
|
} \
|
2009-05-02 23:43:00 +02:00
|
|
|
SETFLAGBIT(AF,false); \
|
|
|
|
} \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(SF,(reg_al&0x80)); \
|
|
|
|
SETFLAGBIT(ZF,(reg_al==0)); \
|
|
|
|
SETFLAGBIT(PF,parity_lookup[reg_al]); \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.type=t_UNKNOWN;
|
2009-05-02 23:43:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
#define AAA() \
|
|
|
|
if (get_AF() || ((reg_al & 0xf) > 9)) \
|
|
|
|
{ \
|
2009-05-03 00:28:34 +02:00
|
|
|
reg_ax += 0x106; \
|
2009-05-02 23:43:00 +02:00
|
|
|
SETFLAGBIT(AF,true); \
|
|
|
|
SETFLAGBIT(CF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(AF,false); \
|
|
|
|
SETFLAGBIT(CF,false); \
|
|
|
|
} \
|
|
|
|
reg_al &= 0x0F; \
|
2009-05-03 00:28:34 +02:00
|
|
|
lflags.type=t_UNKNOWN; \
|
|
|
|
SETFLAGBIT(SF,0); \
|
|
|
|
SETFLAGBIT(OF,0); \
|
|
|
|
SETFLAGBIT(ZF,(reg_al == 0)); \
|
|
|
|
SETFLAGBIT(PF,parity_lookup[reg_al]);
|
2009-05-02 23:43:00 +02:00
|
|
|
|
|
|
|
#define AAS() \
|
|
|
|
if (((reg_al & 0x0f)>9) || get_AF()) { \
|
2009-05-03 00:28:34 +02:00
|
|
|
reg_ax -= 0x106; \
|
2009-05-02 23:43:00 +02:00
|
|
|
SETFLAGBIT(AF,true); \
|
|
|
|
SETFLAGBIT(CF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(AF,false); \
|
|
|
|
SETFLAGBIT(CF,false); \
|
|
|
|
} \
|
|
|
|
reg_al &= 0x0F; \
|
2009-05-03 00:28:34 +02:00
|
|
|
lflags.type=t_UNKNOWN; \
|
|
|
|
SETFLAGBIT(SF,0); \
|
|
|
|
SETFLAGBIT(OF,0); \
|
|
|
|
SETFLAGBIT(ZF,(reg_al == 0)); \
|
|
|
|
SETFLAGBIT(PF,parity_lookup[reg_al]);
|
2009-05-02 23:43:00 +02:00
|
|
|
|
|
|
|
#define AAM(op1) \
|
2009-05-03 00:28:34 +02:00
|
|
|
{ \
|
|
|
|
Bit8u dv=op1; \
|
|
|
|
if (dv!=0) { \
|
|
|
|
reg_ah=reg_al / dv; \
|
|
|
|
reg_al=reg_al % dv; \
|
2009-05-02 23:43:00 +02:00
|
|
|
SETFLAGBIT(SF,(reg_al & 0x80)); \
|
|
|
|
SETFLAGBIT(ZF,(reg_al == 0)); \
|
|
|
|
SETFLAGBIT(PF,parity_lookup[reg_al]); \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(CF,0); \
|
|
|
|
SETFLAGBIT(OF,0); \
|
|
|
|
SETFLAGBIT(AF,0); \
|
|
|
|
lflags.type=t_UNKNOWN; \
|
|
|
|
} else EXCEPTION(0); \
|
|
|
|
}
|
2009-05-02 23:43:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
//Took this from bochs, i seriously hate these weird bcd opcodes
|
|
|
|
#define AAD(op1) \
|
|
|
|
{ \
|
|
|
|
Bit16u ax1 = reg_ah * op1; \
|
|
|
|
Bit16u ax2 = ax1 + reg_al; \
|
|
|
|
reg_al = (Bit8u) ax2; \
|
|
|
|
reg_ah = 0; \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(CF,0); \
|
|
|
|
SETFLAGBIT(OF,0); \
|
|
|
|
SETFLAGBIT(AF,0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
SETFLAGBIT(SF,reg_al >= 0x80); \
|
|
|
|
SETFLAGBIT(ZF,reg_al == 0); \
|
|
|
|
SETFLAGBIT(PF,parity_lookup[reg_al]); \
|
2009-05-02 23:53:27 +02:00
|
|
|
lflags.type=t_UNKNOWN; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MULB(op1,load,save) \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
reg_ax=reg_al*load(op1); \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(ZF,reg_al == 0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (reg_ax & 0xff00) { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MULW(op1,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \
|
|
|
|
reg_ax=(Bit16u)(tempu); \
|
|
|
|
reg_dx=(Bit16u)(tempu >> 16); \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(ZF,reg_ax == 0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (reg_dx) { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MULD(op1,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \
|
|
|
|
reg_eax=(Bit32u)(tempu); \
|
|
|
|
reg_edx=(Bit32u)(tempu >> 32); \
|
2009-05-03 00:28:34 +02:00
|
|
|
SETFLAGBIT(ZF,reg_eax == 0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (reg_edx) { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DIVB(op1,load,save) \
|
|
|
|
{ \
|
|
|
|
Bitu val=load(op1); \
|
|
|
|
if (val==0) EXCEPTION(0); \
|
|
|
|
Bitu quo=reg_ax / val; \
|
2009-05-03 00:18:08 +02:00
|
|
|
Bit8u rem=(Bit8u)(reg_ax % val); \
|
|
|
|
Bit8u quo8=(Bit8u)(quo&0xff); \
|
2009-05-02 23:43:00 +02:00
|
|
|
if (quo>0xff) EXCEPTION(0); \
|
2009-05-03 00:18:08 +02:00
|
|
|
reg_ah=rem; \
|
|
|
|
reg_al=quo8; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DIVW(op1,load,save) \
|
|
|
|
{ \
|
|
|
|
Bitu val=load(op1); \
|
|
|
|
if (val==0) EXCEPTION(0); \
|
2009-05-03 00:28:34 +02:00
|
|
|
Bitu num=((Bit32u)reg_dx<<16)|reg_ax; \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu quo=num/val; \
|
2009-05-03 00:18:08 +02:00
|
|
|
Bit16u rem=(Bit16u)(num % val); \
|
|
|
|
Bit16u quo16=(Bit16u)(quo&0xffff); \
|
|
|
|
if (quo!=(Bit32u)quo16) EXCEPTION(0); \
|
|
|
|
reg_dx=rem; \
|
|
|
|
reg_ax=quo16; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define DIVD(op1,load,save) \
|
|
|
|
{ \
|
|
|
|
Bitu val=load(op1); \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (val==0) EXCEPTION(0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; \
|
|
|
|
Bit64u quo=num/val; \
|
2009-05-03 00:18:08 +02:00
|
|
|
Bit32u rem=(Bit32u)(num % val); \
|
|
|
|
Bit32u quo32=(Bit32u)(quo&0xffffffff); \
|
|
|
|
if (quo!=(Bit64u)quo32) EXCEPTION(0); \
|
|
|
|
reg_edx=rem; \
|
|
|
|
reg_eax=quo32; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define IDIVB(op1,load,save) \
|
|
|
|
{ \
|
|
|
|
Bits val=(Bit8s)(load(op1)); \
|
|
|
|
if (val==0) EXCEPTION(0); \
|
|
|
|
Bits quo=((Bit16s)reg_ax) / val; \
|
2009-05-03 00:18:08 +02:00
|
|
|
Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); \
|
|
|
|
Bit8s quo8s=(Bit8s)(quo&0xff); \
|
|
|
|
if (quo!=(Bit16s)quo8s) EXCEPTION(0); \
|
|
|
|
reg_ah=rem; \
|
|
|
|
reg_al=quo8s; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define IDIVW(op1,load,save) \
|
|
|
|
{ \
|
|
|
|
Bits val=(Bit16s)(load(op1)); \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (val==0) EXCEPTION(0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bits num=(Bit32s)((reg_dx<<16)|reg_ax); \
|
|
|
|
Bits quo=num/val; \
|
2009-05-03 00:18:08 +02:00
|
|
|
Bit16s rem=(Bit16s)(num % val); \
|
|
|
|
Bit16s quo16s=(Bit16s)quo; \
|
|
|
|
if (quo!=(Bit32s)quo16s) EXCEPTION(0); \
|
|
|
|
reg_dx=rem; \
|
|
|
|
reg_ax=quo16s; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define IDIVD(op1,load,save) \
|
|
|
|
{ \
|
|
|
|
Bits val=(Bit32s)(load(op1)); \
|
2009-05-03 00:28:34 +02:00
|
|
|
if (val==0) EXCEPTION(0); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; \
|
|
|
|
Bit64s quo=num/val; \
|
2009-05-03 00:18:08 +02:00
|
|
|
Bit32s rem=(Bit32s)(num % val); \
|
|
|
|
Bit32s quo32s=(Bit32s)(quo&0xffffffff); \
|
|
|
|
if (quo!=(Bit64s)quo32s) EXCEPTION(0); \
|
|
|
|
reg_edx=rem; \
|
|
|
|
reg_eax=quo32s; \
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define IMULB(op1,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \
|
|
|
|
if ((reg_ax & 0xff80)==0xff80 || \
|
|
|
|
(reg_ax & 0xff80)==0x0000) { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define IMULW(op1,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \
|
|
|
|
reg_ax=(Bit16s)(temps); \
|
|
|
|
reg_dx=(Bit16s)(temps >> 16); \
|
|
|
|
if (((temps & 0xffff8000)==0xffff8000 || \
|
|
|
|
(temps & 0xffff8000)==0x0000)) { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define IMULD(op1,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \
|
|
|
|
((Bit64s)((Bit32s)(load(op1)))); \
|
|
|
|
reg_eax=(Bit32u)(temps); \
|
|
|
|
reg_edx=(Bit32u)(temps >> 32); \
|
|
|
|
if ((reg_edx==0xffffffff) && \
|
|
|
|
(reg_eax & 0x80000000) ) { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} else if ( (reg_edx==0x00000000) && \
|
|
|
|
(reg_eax< 0x80000000) ) { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DIMULW(op1,op2,op3,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bits res; \
|
|
|
|
res=((Bit16s)op2) * ((Bit16s)op3); \
|
|
|
|
save(op1,res & 0xffff); \
|
|
|
|
if ((res> -32768) && (res<32767)) { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DIMULD(op1,op2,op3,load,save) \
|
|
|
|
{ \
|
2009-05-03 00:02:15 +02:00
|
|
|
FillFlags(); \
|
2009-05-02 23:43:00 +02:00
|
|
|
Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \
|
|
|
|
save(op1,(Bit32s)res); \
|
|
|
|
if ((res>-((Bit64s)(2147483647)+1)) && \
|
|
|
|
(res<(Bit64s)2147483647)) { \
|
|
|
|
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
|
|
|
} else { \
|
|
|
|
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
#define GRP2B(blah) \
|
|
|
|
{ \
|
2009-05-02 23:43:00 +02:00
|
|
|
GetRM;Bitu which=(rm>>3)&7; \
|
2009-05-02 23:03:37 +02:00
|
|
|
if (rm >= 0xc0) { \
|
|
|
|
GetEArb; \
|
|
|
|
Bit8u val=blah & 0x1f; \
|
2009-05-02 23:43:00 +02:00
|
|
|
switch (which) { \
|
2009-05-02 23:03:37 +02:00
|
|
|
case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01:RORB(*earb,val,LoadRb,SaveRb);break; \
|
|
|
|
case 0x02:RCLB(*earb,val,LoadRb,SaveRb);break; \
|
|
|
|
case 0x03:RCRB(*earb,val,LoadRb,SaveRb);break; \
|
|
|
|
case 0x04:/* SHL and SAL are the same */ \
|
|
|
|
case 0x06:SHLB(*earb,val,LoadRb,SaveRb);break; \
|
|
|
|
case 0x05:SHRB(*earb,val,LoadRb,SaveRb);break; \
|
|
|
|
case 0x07:SARB(*earb,val,LoadRb,SaveRb);break; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
|
|
|
} else { \
|
|
|
|
GetEAa; \
|
|
|
|
Bit8u val=blah & 0x1f; \
|
2009-05-02 23:43:00 +02:00
|
|
|
switch (which) { \
|
2009-05-02 23:03:37 +02:00
|
|
|
case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01:RORB(eaa,val,LoadMb,SaveMb);break; \
|
|
|
|
case 0x02:RCLB(eaa,val,LoadMb,SaveMb);break; \
|
|
|
|
case 0x03:RCRB(eaa,val,LoadMb,SaveMb);break; \
|
|
|
|
case 0x04:/* SHL and SAL are the same */ \
|
|
|
|
case 0x06:SHLB(eaa,val,LoadMb,SaveMb);break; \
|
|
|
|
case 0x05:SHRB(eaa,val,LoadMb,SaveMb);break; \
|
|
|
|
case 0x07:SARB(eaa,val,LoadMb,SaveMb);break; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define GRP2W(blah) \
|
|
|
|
{ \
|
2009-05-02 23:43:00 +02:00
|
|
|
GetRM;Bitu which=(rm>>3)&7; \
|
2009-05-02 23:03:37 +02:00
|
|
|
if (rm >= 0xc0) { \
|
|
|
|
GetEArw; \
|
|
|
|
Bit8u val=blah & 0x1f; \
|
2009-05-02 23:43:00 +02:00
|
|
|
switch (which) { \
|
2009-05-02 23:03:37 +02:00
|
|
|
case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01:RORW(*earw,val,LoadRw,SaveRw);break; \
|
|
|
|
case 0x02:RCLW(*earw,val,LoadRw,SaveRw);break; \
|
|
|
|
case 0x03:RCRW(*earw,val,LoadRw,SaveRw);break; \
|
|
|
|
case 0x04:/* SHL and SAL are the same */ \
|
|
|
|
case 0x06:SHLW(*earw,val,LoadRw,SaveRw);break; \
|
|
|
|
case 0x05:SHRW(*earw,val,LoadRw,SaveRw);break; \
|
|
|
|
case 0x07:SARW(*earw,val,LoadRw,SaveRw);break; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
|
|
|
} else { \
|
|
|
|
GetEAa; \
|
|
|
|
Bit8u val=blah & 0x1f; \
|
2009-05-02 23:43:00 +02:00
|
|
|
switch (which) { \
|
2009-05-02 23:03:37 +02:00
|
|
|
case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01:RORW(eaa,val,LoadMw,SaveMw);break; \
|
|
|
|
case 0x02:RCLW(eaa,val,LoadMw,SaveMw);break; \
|
|
|
|
case 0x03:RCRW(eaa,val,LoadMw,SaveMw);break; \
|
|
|
|
case 0x04:/* SHL and SAL are the same */ \
|
|
|
|
case 0x06:SHLW(eaa,val,LoadMw,SaveMw);break; \
|
|
|
|
case 0x05:SHRW(eaa,val,LoadMw,SaveMw);break; \
|
|
|
|
case 0x07:SARW(eaa,val,LoadMw,SaveMw);break; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define GRP2D(blah) \
|
|
|
|
{ \
|
2009-05-02 23:43:00 +02:00
|
|
|
GetRM;Bitu which=(rm>>3)&7; \
|
2009-05-02 23:03:37 +02:00
|
|
|
if (rm >= 0xc0) { \
|
|
|
|
GetEArd; \
|
|
|
|
Bit8u val=blah & 0x1f; \
|
2009-05-02 23:43:00 +02:00
|
|
|
switch (which) { \
|
2009-05-02 23:03:37 +02:00
|
|
|
case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01:RORD(*eard,val,LoadRd,SaveRd);break; \
|
|
|
|
case 0x02:RCLD(*eard,val,LoadRd,SaveRd);break; \
|
|
|
|
case 0x03:RCRD(*eard,val,LoadRd,SaveRd);break; \
|
|
|
|
case 0x04:/* SHL and SAL are the same */ \
|
|
|
|
case 0x06:SHLD(*eard,val,LoadRd,SaveRd);break; \
|
|
|
|
case 0x05:SHRD(*eard,val,LoadRd,SaveRd);break; \
|
|
|
|
case 0x07:SARD(*eard,val,LoadRd,SaveRd);break; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
|
|
|
} else { \
|
|
|
|
GetEAa; \
|
|
|
|
Bit8u val=blah & 0x1f; \
|
2009-05-02 23:43:00 +02:00
|
|
|
switch (which) { \
|
2009-05-02 23:03:37 +02:00
|
|
|
case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01:RORD(eaa,val,LoadMd,SaveMd);break; \
|
|
|
|
case 0x02:RCLD(eaa,val,LoadMd,SaveMd);break; \
|
|
|
|
case 0x03:RCRD(eaa,val,LoadMd,SaveMd);break; \
|
|
|
|
case 0x04:/* SHL and SAL are the same */ \
|
|
|
|
case 0x06:SHLD(eaa,val,LoadMd,SaveMd);break; \
|
|
|
|
case 0x05:SHRD(eaa,val,LoadMd,SaveMd);break; \
|
|
|
|
case 0x07:SARD(eaa,val,LoadMd,SaveMd);break; \
|
2009-05-02 23:03:37 +02:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* let's hope bochs has it correct with the higher than 16 shifts */
|
2009-05-02 23:12:18 +02:00
|
|
|
/* double-precision shift left has low bits in second argument */
|
2009-05-02 23:03:37 +02:00
|
|
|
#define DSHLW(op1,op2,op3,load,save) \
|
2009-05-02 23:12:18 +02:00
|
|
|
Bit8u val=op3 & 0x1F; \
|
|
|
|
if (!val) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var2b=val;lf_var1d=(load(op1)<<16)|op2; \
|
|
|
|
Bit32u tempd=lf_var1d << lf_var2b; \
|
|
|
|
if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); \
|
|
|
|
lf_resw=(Bit16u)(tempd >> 16); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_DSHLw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
#define DSHLD(op1,op2,op3,load,save) \
|
|
|
|
Bit8u val=op3 & 0x1F; \
|
|
|
|
if (!val) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var2b=val;lf_var1d=load(op1); \
|
|
|
|
lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_DSHLd;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
/* double-precision shift right has high bits in second argument */
|
2009-05-02 23:03:37 +02:00
|
|
|
#define DSHRW(op1,op2,op3,load,save) \
|
2009-05-02 23:12:18 +02:00
|
|
|
Bit8u val=op3 & 0x1F; \
|
|
|
|
if (!val) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var2b=val;lf_var1d=(op2<<16)|load(op1); \
|
|
|
|
Bit32u tempd=lf_var1d >> lf_var2b; \
|
|
|
|
if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); \
|
|
|
|
lf_resw=(Bit16u)(tempd); \
|
|
|
|
save(op1,lf_resw); \
|
|
|
|
lflags.type=t_DSHRw;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
#define DSHRD(op1,op2,op3,load,save) \
|
|
|
|
Bit8u val=op3 & 0x1F; \
|
|
|
|
if (!val) break; \
|
2009-05-02 23:53:27 +02:00
|
|
|
lf_var2b=val;lf_var1d=load(op1); \
|
|
|
|
lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); \
|
|
|
|
save(op1,lf_resd); \
|
|
|
|
lflags.type=t_DSHRd;
|
2009-05-02 23:12:18 +02:00
|
|
|
|
|
|
|
#define BSWAP(op1) \
|
|
|
|
op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000);
|