Only enable heavy_debug if normal debug is enabled. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@637
654 lines
21 KiB
C
654 lines
21 KiB
C
/*
|
|
* Copyright (C) 2002 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 Library 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.
|
|
*/
|
|
|
|
/* Jumps */
|
|
|
|
/*
|
|
Could perhaps do some things with 8 and 16 bit operations like shifts, doing them in 32 bit regs
|
|
*/
|
|
|
|
#define JumpSIb(blah) \
|
|
if (blah) { \
|
|
ADDIPFAST(Fetchbs()); \
|
|
} else { \
|
|
ADDIPFAST(1); \
|
|
}
|
|
|
|
#define JumpSIw(blah) \
|
|
if (blah) { \
|
|
ADDIPFAST(Fetchws()); \
|
|
} else { \
|
|
ADDIPFAST(2); \
|
|
}
|
|
|
|
#define SETcc(cc) \
|
|
{ \
|
|
GetRM; \
|
|
if (rm >= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;} \
|
|
else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);} \
|
|
}
|
|
|
|
#define INTERRUPT(blah) \
|
|
{ \
|
|
Bit8u new_num=blah; \
|
|
SAVEIP; \
|
|
Interrupt(new_num); \
|
|
LOADIP; \
|
|
}
|
|
|
|
|
|
|
|
/* All Byte genereal instructions */
|
|
#define ADDB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b+flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_ADDb;
|
|
|
|
#define ADCB(op1,op2,load,save) \
|
|
flags.oldcf=get_CF(); \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b+flags.var2.b+flags.oldcf; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_ADCb;
|
|
|
|
#define SBBB(op1,op2,load,save) \
|
|
flags.oldcf=get_CF(); \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b-(flags.var2.b+flags.oldcf); \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_SBBb;
|
|
|
|
#define SUBB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b-flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_SUBb;
|
|
|
|
#define ORB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b | flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_ORb;
|
|
|
|
#define XORB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b ^ flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_XORb;
|
|
|
|
#define ANDB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b & flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_ANDb;
|
|
|
|
#define CMPB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b-flags.var2.b; \
|
|
flags.type=t_CMPb;
|
|
|
|
#define TESTB(op1,op2,load,save) \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b & flags.var2.b; \
|
|
flags.type=t_TESTb;
|
|
|
|
/* All Word General instructions */
|
|
|
|
#define ADDW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w+flags.var2.w; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_ADDw;
|
|
|
|
#define ADCW(op1,op2,load,save) \
|
|
flags.oldcf=get_CF(); \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w+flags.var2.w+flags.oldcf; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_ADCw;
|
|
|
|
#define SBBW(op1,op2,load,save) \
|
|
flags.oldcf=get_CF(); \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w-(flags.var2.w+flags.oldcf); \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_SBBw;
|
|
|
|
#define SUBW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w-flags.var2.w; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_SUBw;
|
|
|
|
#define ORW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w | flags.var2.w; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_ORw;
|
|
|
|
#define XORW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w ^ flags.var2.w; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_XORw;
|
|
|
|
#define ANDW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w & flags.var2.w; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_ANDw;
|
|
|
|
#define CMPW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w-flags.var2.w; \
|
|
flags.type=t_CMPw;
|
|
|
|
#define TESTW(op1,op2,load,save) \
|
|
flags.var1.w=load(op1);flags.var2.w=op2; \
|
|
flags.result.w=flags.var1.w & flags.var2.w; \
|
|
flags.type=t_TESTw;
|
|
|
|
/* All DWORD General Instructions */
|
|
|
|
#define ADDD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d+flags.var2.d; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_ADDd;
|
|
|
|
#define ADCD(op1,op2,load,save) \
|
|
flags.oldcf=get_CF(); \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d+flags.var2.d+flags.oldcf; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_ADCd;
|
|
|
|
#define SBBD(op1,op2,load,save) \
|
|
flags.oldcf=get_CF(); \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d-(flags.var2.d+flags.oldcf); \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_SBBd;
|
|
|
|
#define SUBD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d-flags.var2.d; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_SUBd;
|
|
|
|
#define ORD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d | flags.var2.d; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_ORd;
|
|
|
|
#define XORD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d ^ flags.var2.d; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_XORd;
|
|
|
|
#define ANDD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d & flags.var2.d; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_ANDd;
|
|
|
|
#define CMPD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d-flags.var2.d; \
|
|
flags.type=t_CMPd;
|
|
|
|
|
|
#define TESTD(op1,op2,load,save) \
|
|
flags.var1.d=load(op1);flags.var2.d=op2; \
|
|
flags.result.d=flags.var1.d & flags.var2.d; \
|
|
flags.type=t_TESTd;
|
|
|
|
|
|
|
|
|
|
#define INCB(op1,load,save) \
|
|
LoadCF;flags.result.b=load(op1)+1; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_INCb; \
|
|
|
|
#define INCW(op1,load,save) \
|
|
LoadCF;flags.result.w=load(op1)+1; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_INCw;
|
|
|
|
#define INCD(op1,load,save) \
|
|
LoadCF;flags.result.d=load(op1)+1; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_INCd;
|
|
|
|
#define DECB(op1,load,save) \
|
|
LoadCF;flags.result.b=load(op1)-1; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_DECb;
|
|
|
|
#define DECW(op1,load,save) \
|
|
LoadCF;flags.result.w=load(op1)-1; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_DECw;
|
|
|
|
#define DECD(op1,load,save) \
|
|
LoadCF;flags.result.d=load(op1)-1; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_DECd;
|
|
|
|
#define NOTDONE \
|
|
SUBIP(1);E_Exit("CPU:Opcode %2X Unhandled",Fetchb());
|
|
|
|
#define NOTDONE66 \
|
|
SUBIP(1);E_Exit("CPU:Opcode 66:%2X Unhandled",Fetchb());
|
|
|
|
|
|
//TODO Maybe make this into a bigger split up because of the rm >=0xc0 this seems make it a bit slower
|
|
//TODO set Zero and Sign flag in one run
|
|
#define ROLB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.var2.b=op2&0x07;flags.var1.b=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.b=flags.var1.b; \
|
|
} else { \
|
|
flags.result.b=(flags.var1.b << flags.var2.b) | \
|
|
(flags.var1.b >> (8-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_ROLb;
|
|
|
|
#define ROLW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.w=flags.var1.w; \
|
|
} else { \
|
|
flags.result.w=(flags.var1.w << flags.var2.b) | \
|
|
(flags.var1.w >> (16-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_ROLw;
|
|
|
|
#define ROLD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
|
flags.result.d=(flags.var1.d << flags.var2.b) | \
|
|
(flags.var1.d >> (32-flags.var2.b)); \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_ROLd;
|
|
|
|
|
|
#define RORB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.var2.b=op2&0x07;flags.var1.b=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.b=flags.var1.b; \
|
|
} else { \
|
|
flags.result.b=(flags.var1.b >> flags.var2.b) | \
|
|
(flags.var1.b << (8-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_RORb;
|
|
|
|
#define RORW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.w=flags.var1.w; \
|
|
} else { \
|
|
flags.result.w=(flags.var1.w >> flags.var2.b) | \
|
|
(flags.var1.w << (16-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_RORw;
|
|
|
|
#define RORD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
|
flags.result.d=(flags.var1.d >> flags.var2.b) | \
|
|
(flags.var1.d << (32-flags.var2.b)); \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_RORd;
|
|
|
|
|
|
/* flags.oldcf=get_CF();*/ \
|
|
|
|
#define RCLB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.cf=get_CF();flags.type=t_RCLb; \
|
|
flags.var2.b=op2%9;flags.var1.b=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.b=flags.var1.b; \
|
|
} else { \
|
|
flags.result.b=(flags.var1.b << flags.var2.b) | \
|
|
(flags.cf << (flags.var2.b-1)) | \
|
|
(flags.var1.b >> (9-flags.var2.b)); \
|
|
flags.cf=((flags.var1.b >> (8-flags.var2.b)) & 1); \
|
|
} \
|
|
flags.of=((flags.result.b & 0x80) ^ (flags.cf ? 0x80 : 0)) != 0; \
|
|
save(op1,flags.result.b);
|
|
|
|
#define RCLW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.cf=get_CF();flags.type=t_RCLw; \
|
|
flags.var2.b=op2%17;flags.var1.w=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.w=flags.var1.w; \
|
|
} else { \
|
|
flags.result.w=(flags.var1.w << flags.var2.b) | \
|
|
(flags.cf << (flags.var2.b-1)) | \
|
|
(flags.var1.w >> (17-flags.var2.b)); \
|
|
flags.cf=((flags.var1.w >> (16-flags.var2.b)) & 1); \
|
|
} \
|
|
flags.of=((flags.result.w & 0x8000) ^ (flags.cf ? 0x8000 : 0)) != 0; \
|
|
save(op1,flags.result.w);
|
|
|
|
#define RCLD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.cf=get_CF();flags.type=t_RCLd; \
|
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
|
if (flags.var2.b==1) { \
|
|
flags.result.d=(flags.var1.d << 1) | flags.cf; \
|
|
} else { \
|
|
flags.result.d=(flags.var1.d << flags.var2.b) | \
|
|
(flags.cf << (flags.var2.b-1)) | \
|
|
(flags.var1.d >> (33-flags.var2.b)); \
|
|
} \
|
|
flags.cf=((flags.var1.d >> (32-flags.var2.b)) & 1); \
|
|
flags.of=((flags.result.d & 0x80000000) ^ (flags.cf ? 0x80000000 : 0)) != 0; \
|
|
save(op1,flags.result.d);
|
|
|
|
#define RCRB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.cf=get_CF();flags.type=t_RCRb; \
|
|
flags.var2.b=op2%9;flags.var1.b=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.b=flags.var1.b; \
|
|
} else { \
|
|
flags.result.b=(flags.var1.b >> flags.var2.b) | \
|
|
(flags.cf << (8-flags.var2.b)) | \
|
|
(flags.var1.b << (9-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.b);
|
|
|
|
#define RCRW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.cf=get_CF();flags.type=t_RCRw; \
|
|
flags.var2.b=op2%17;flags.var1.w=load(op1); \
|
|
if (!flags.var2.b) { \
|
|
flags.result.w=flags.var1.w; \
|
|
} else { \
|
|
flags.result.w=(flags.var1.w >> flags.var2.b) | \
|
|
(flags.cf << (16-flags.var2.b)) | \
|
|
(flags.var1.w << (17-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.w);
|
|
|
|
#define RCRD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
|
flags.cf=get_CF();flags.type=t_RCRd; \
|
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
|
if (flags.var2.b==1) { \
|
|
flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \
|
|
} else { \
|
|
flags.result.d=(flags.var1.d >> flags.var2.b) | \
|
|
(flags.cf << (32-flags.var2.b)) | \
|
|
(flags.var1.d << (33-flags.var2.b)); \
|
|
} \
|
|
save(op1,flags.result.d);
|
|
|
|
|
|
#define SHLB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b << flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_SHLb;
|
|
|
|
#define SHLW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.w=load(op1);flags.var2.b=op2 ; \
|
|
flags.result.w=flags.var1.w << flags.var2.b; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_SHLw;
|
|
|
|
#define SHLD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.d=load(op1);flags.var2.b=op2; \
|
|
flags.result.d=flags.var1.d << flags.var2.b; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_SHLd;
|
|
|
|
|
|
#define SHRB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
flags.result.b=flags.var1.b >> flags.var2.b; \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_SHRb;
|
|
|
|
#define SHRW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.w=load(op1);flags.var2.b=op2; \
|
|
flags.result.w=flags.var1.w >> flags.var2.b; \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_SHRw;
|
|
|
|
#define SHRD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.d=load(op1);flags.var2.b=op2; \
|
|
flags.result.d=flags.var1.d >> flags.var2.b; \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_SHRd;
|
|
|
|
|
|
#define SARB(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
|
if (flags.var2.b>8) flags.var2.b=8; \
|
|
if (flags.var1.b & 0x80) { \
|
|
flags.result.b=(flags.var1.b >> flags.var2.b)| \
|
|
(0xff << (8 - flags.var2.b)); \
|
|
} else { \
|
|
flags.result.b=flags.var1.b >> flags.var2.b; \
|
|
} \
|
|
save(op1,flags.result.b); \
|
|
flags.type=t_SARb;
|
|
|
|
#define SARW(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var1.w=load(op1);flags.var2.b=op2; \
|
|
if (flags.var2.b>16) flags.var2.b=16; \
|
|
if (flags.var1.w & 0x8000) { \
|
|
flags.result.w=(flags.var1.w >> flags.var2.b)| \
|
|
(0xffff << (16 - flags.var2.b)); \
|
|
} else { \
|
|
flags.result.w=flags.var1.w >> flags.var2.b; \
|
|
} \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_SARw;
|
|
|
|
#define SARD(op1,op2,load,save) \
|
|
if (!op2) break; \
|
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
|
if (flags.var1.d & 0x80000000) { \
|
|
flags.result.d=(flags.var1.d >> flags.var2.b)| \
|
|
(0xffffffff << (32 - flags.var2.b)); \
|
|
} else { \
|
|
flags.result.d=flags.var1.d >> flags.var2.b; \
|
|
} \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_SARd;
|
|
|
|
|
|
|
|
#define GRP2B(blah) \
|
|
{ \
|
|
GetRM; \
|
|
if (rm >= 0xc0) { \
|
|
GetEArb; \
|
|
Bit8u val=blah & 0x1f; \
|
|
switch (rm&0x38) { \
|
|
case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \
|
|
case 0x08:RORB(*earb,val,LoadRb,SaveRb);break; \
|
|
case 0x10:RCLB(*earb,val,LoadRb,SaveRb);break; \
|
|
case 0x18:RCRB(*earb,val,LoadRb,SaveRb);break; \
|
|
case 0x20:/* SHL and SAL are the same */ \
|
|
case 0x30:SHLB(*earb,val,LoadRb,SaveRb);break; \
|
|
case 0x28:SHRB(*earb,val,LoadRb,SaveRb);break; \
|
|
case 0x38:SARB(*earb,val,LoadRb,SaveRb);break; \
|
|
} \
|
|
} else { \
|
|
GetEAa; \
|
|
Bit8u val=blah & 0x1f; \
|
|
switch (rm & 0x38) { \
|
|
case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \
|
|
case 0x08:RORB(eaa,val,LoadMb,SaveMb);break; \
|
|
case 0x10:RCLB(eaa,val,LoadMb,SaveMb);break; \
|
|
case 0x18:RCRB(eaa,val,LoadMb,SaveMb);break; \
|
|
case 0x20:/* SHL and SAL are the same */ \
|
|
case 0x30:SHLB(eaa,val,LoadMb,SaveMb);break; \
|
|
case 0x28:SHRB(eaa,val,LoadMb,SaveMb);break; \
|
|
case 0x38:SARB(eaa,val,LoadMb,SaveMb);break; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
#define GRP2W(blah) \
|
|
{ \
|
|
GetRM; \
|
|
if (rm >= 0xc0) { \
|
|
GetEArw; \
|
|
Bit8u val=blah & 0x1f; \
|
|
switch (rm&0x38) { \
|
|
case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \
|
|
case 0x08:RORW(*earw,val,LoadRw,SaveRw);break; \
|
|
case 0x10:RCLW(*earw,val,LoadRw,SaveRw);break; \
|
|
case 0x18:RCRW(*earw,val,LoadRw,SaveRw);break; \
|
|
case 0x20:/* SHL and SAL are the same */ \
|
|
case 0x30:SHLW(*earw,val,LoadRw,SaveRw);break; \
|
|
case 0x28:SHRW(*earw,val,LoadRw,SaveRw);break; \
|
|
case 0x38:SARW(*earw,val,LoadRw,SaveRw);break; \
|
|
} \
|
|
} else { \
|
|
GetEAa; \
|
|
Bit8u val=blah & 0x1f; \
|
|
switch (rm & 0x38) { \
|
|
case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \
|
|
case 0x08:RORW(eaa,val,LoadMw,SaveMw);break; \
|
|
case 0x10:RCLW(eaa,val,LoadMw,SaveMw);break; \
|
|
case 0x18:RCRW(eaa,val,LoadMw,SaveMw);break; \
|
|
case 0x20:/* SHL and SAL are the same */ \
|
|
case 0x30:SHLW(eaa,val,LoadMw,SaveMw);break; \
|
|
case 0x28:SHRW(eaa,val,LoadMw,SaveMw);break; \
|
|
case 0x38:SARW(eaa,val,LoadMw,SaveMw);break; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
#define GRP2D(blah) \
|
|
{ \
|
|
GetRM; \
|
|
if (rm >= 0xc0) { \
|
|
GetEArd; \
|
|
Bit8u val=blah & 0x1f; \
|
|
switch (rm&0x38) { \
|
|
case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \
|
|
case 0x08:RORD(*eard,val,LoadRd,SaveRd);break; \
|
|
case 0x10:RCLD(*eard,val,LoadRd,SaveRd);break; \
|
|
case 0x18:RCRD(*eard,val,LoadRd,SaveRd);break; \
|
|
case 0x20:/* SHL and SAL are the same */ \
|
|
case 0x30:SHLD(*eard,val,LoadRd,SaveRd);break; \
|
|
case 0x28:SHRD(*eard,val,LoadRd,SaveRd);break; \
|
|
case 0x38:SARD(*eard,val,LoadRd,SaveRd);break; \
|
|
} \
|
|
} else { \
|
|
GetEAa; \
|
|
Bit8u val=blah & 0x1f; \
|
|
switch (rm & 0x38) { \
|
|
case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \
|
|
case 0x08:RORD(eaa,val,LoadMd,SaveMd);break; \
|
|
case 0x10:RCLD(eaa,val,LoadMd,SaveMd);break; \
|
|
case 0x18:RCRD(eaa,val,LoadMd,SaveMd);break; \
|
|
case 0x20:/* SHL and SAL are the same */ \
|
|
case 0x30:SHLD(eaa,val,LoadMd,SaveMd);break; \
|
|
case 0x28:SHRD(eaa,val,LoadMd,SaveMd);break; \
|
|
case 0x38:SARD(eaa,val,LoadMd,SaveMd);break; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
/* let's hope bochs has it correct with the higher than 16 shifts */
|
|
/* double-precision shift left has low bits in second argument */
|
|
#define DSHLW(op1,op2,op3,load,save) \
|
|
Bit8u val=op3 & 0x1F; \
|
|
if (!val) break; \
|
|
flags.var2.b=val;flags.var1.d=(load(op1)<<16)|op2; \
|
|
Bit32u tempd=flags.var1.d << flags.var2.b; \
|
|
if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \
|
|
flags.result.w=(Bit16u)(tempd >> 16); \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_DSHLw;
|
|
|
|
#define DSHLD(op1,op2,op3,load,save) \
|
|
Bit8u val=op3 & 0x1F; \
|
|
if (!val) break; \
|
|
flags.var2.b=val;flags.var1.d=load(op1); \
|
|
flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_DSHLd;
|
|
|
|
/* double-precision shift right has high bits in second argument */
|
|
#define DSHRW(op1,op2,op3,load,save) \
|
|
Bit8u val=op3 & 0x1F; \
|
|
if (!val) break; \
|
|
flags.var2.b=val;flags.var1.d=(op2<<16)|load(op1); \
|
|
Bit32u tempd=flags.var1.d >> flags.var2.b; \
|
|
if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \
|
|
flags.result.w=(Bit16u)(tempd); \
|
|
save(op1,flags.result.w); \
|
|
flags.type=t_DSHRw;
|
|
|
|
#define DSHRD(op1,op2,op3,load,save) \
|
|
Bit8u val=op3 & 0x1F; \
|
|
if (!val) break; \
|
|
flags.var2.b=val;flags.var1.d=load(op1); \
|
|
flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \
|
|
save(op1,flags.result.d); \
|
|
flags.type=t_DSHRd;
|
|
|
|
#define BSWAP(op1) \
|
|
op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000);
|