blob: cb60407e66c0aeb568bf21730db0307d3941017e [file] [log] [blame] [raw]
/*
* Dos/PC Emulator
* Copyright (C) 1991 Jim Hudgens
*
*
* The file is part of GDE.
*
* GDE 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 1, or (at your option)
* any later version.
*
* GDE 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 GDE; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "altairz80_defs.h"
#include "i86.h"
extern void out(const uint32 Port, const uint32 Value);
extern uint32 in(const uint32 Port);
/* $Log: i86_ops.c,v $
* Revision 0.11 1991/07/30 02:02:04 hudgens
* added copyright.
*
* Revision 0.10 1991/07/21 18:22:08 hudgens
* Fixed problem with scans, which was the result of the loop break
* condition being incorrect when used in conjunction with the repe
* or repne prefixes. Eureka. pkzip/pkunzip now compress/decompress
* correctly.
*
* Revision 0.9 1991/07/21 03:33:18 hudgens
* fixed popf so that it appears to be the same as an 8088 popf, and always
* sets the high 4 bits of the flags.
*
* Revision 0.8 1991/07/21 01:44:11 hudgens
* fixed aad and aam instructions.
*
* Revision 0.7 1991/07/21 00:31:24 hudgens
* Fixed iret so that it works correctly.
*
* Revision 0.6 1991/07/20 16:54:50 hudgens
* removed the 8087 coprocessor operations. Moved to i87_ops.c
*
* Revision 0.5 1991/07/17 03:50:10 hudgens
* Minor modifications.
*
* Revision 0.4 1991/06/18 02:48:41 hudgens
* Fixed a problem with scasb and scasw.
*
* Revision 0.3 1991/06/03 01:01:10 hudgens
* fixed minor problems due to unsigned to signed short integer
* promotions.
*
* Revision 0.2 1991/03/31 01:32:10 hudgens
* fixed segment handling. Added calls to DECODE_CLEAR_SEGOVR in
* many places in the code. Should work much better now.
*
* Revision 0.1 1991/03/30 21:15:48 hudgens
* Initial checkin to RCS.
*
*
*/
/* 2/23/91 fixed decode for operand x87. */
/* partially mechanically generated file....(based on the optable) */
/*
There are approximately 250 subroutines in here, which correspond
to the 256 byte-"opcodes" found on the 8086. The table which
dispatches this is found in the files optab.[ch].
Each opcode proc has a comment preceeding it which gives it's table
address. Several opcodes are missing (undefined) in the table.
Each proc includes information for decoding (DECODE_PRINTF and
and misc functions (
Many of the procedures are *VERY* similar in coding. This has
allowed for a very large amount of code to be generated in a fairly
short amount of time (i.e. cut, paste, and modify).
The result is that much of the code below could
have been folded into subroutines for a large reduction in size of
this file. The downside would be that there would be a penalty in
execution speed. The file could also have been *MUCH* larger by
inlining certain functions which were called. This could have
resulted even faster execution. The prime directive I used to decide
whether to inline the code or to modularize it, was basically: 1) no
unnecessary subroutine calls, 2) no routines more than about 200 lines
in size, and 3) modularize any code that I might not get right the first
time. The fetch_* subroutines fall into the latter category. The
The decode_* fall into the second category. The coding of the
"switch(mod){ .... }" in many of the subroutines below falls into the
first category. Especially, the coding of {add,and,or,sub,...}_{byte,word}
subroutines are an especially glaring case of the third guideline.
Since so much of the code is cloned from other modules (compare
opcode #00 to opcode #01), making the basic operations subroutine calls
is especially important; otherwise mistakes in coding an "add"
would represent a nightmare in maintenance.
So, without further ado, ...
*/
extern uint8 parity_tab[];
static void i86op_illegal_op(PC_ENV *m)
{
intr |= INTR_ILLEGAL_OPCODE;
}
/*opcode=0x00*/
static void i86op_add_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = add_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = add_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = add_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = add_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x01*/
static void i86op_add_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = add_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = add_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = add_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = add_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x02*/
static void i86op_add_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = add_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = add_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = add_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = add_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x03*/
static void i86op_add_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = add_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = add_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = add_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = add_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x04*/
static void i86op_add_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = add_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x05*/
static void i86op_add_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = add_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x06*/
static void i86op_push_ES(PC_ENV *m)
{
push_word(m,m->R_ES);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x07*/
static void i86op_pop_ES(PC_ENV *m)
{
m->R_ES = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x08*/
static void i86op_or_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = or_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = or_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = or_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = or_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x09*/
static void i86op_or_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = or_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = or_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = or_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = or_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x0a*/
static void i86op_or_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = or_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = or_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = or_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = or_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x0b*/
static void i86op_or_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = or_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = or_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = or_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = or_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x0c*/
static void i86op_or_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = or_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x0d*/
static void i86op_or_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = or_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x0e*/
static void i86op_push_CS(PC_ENV *m)
{
push_word(m,m->R_CS);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x0f === ILLEGAL OP*/
/*opcode=0x10*/
static void i86op_adc_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = adc_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = adc_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = adc_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = adc_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x11*/
static void i86op_adc_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = adc_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = adc_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = adc_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = adc_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x12*/
static void i86op_adc_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = adc_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = adc_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = adc_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = adc_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x13*/
static void i86op_adc_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = adc_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = adc_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = adc_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = adc_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x14*/
static void i86op_adc_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = adc_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x15*/
static void i86op_adc_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = adc_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x16*/
static void i86op_push_SS(PC_ENV *m)
{
push_word(m,m->R_SS);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x17*/
static void i86op_pop_SS(PC_ENV *m)
{
m->R_SS = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x18*/
static void i86op_sbb_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = sbb_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = sbb_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = sbb_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = sbb_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x19*/
static void i86op_sbb_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = sbb_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = sbb_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = sbb_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = sbb_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x1a*/
static void i86op_sbb_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = sbb_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = sbb_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = sbb_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = sbb_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x1b*/
static void i86op_sbb_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = sbb_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = sbb_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = sbb_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = sbb_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x1c*/
static void i86op_sbb_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = sbb_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x1d*/
static void i86op_sbb_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = sbb_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x1e*/
static void i86op_push_DS(PC_ENV *m)
{
push_word(m,m->R_DS);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x1f*/
static void i86op_pop_DS(PC_ENV *m)
{
m->R_DS = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x20*/
static void i86op_and_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = and_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = and_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = and_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = and_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x21*/
static void i86op_and_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = and_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = and_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = and_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = and_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x22*/
static void i86op_and_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = and_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = and_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = and_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = and_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x23*/
static void i86op_and_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = and_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = and_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = and_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = and_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x24*/
static void i86op_and_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = and_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x25*/
static void i86op_and_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = and_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x26*/
static void i86op_segovr_ES(PC_ENV *m)
{
m->sysmode |= SYSMODE_SEGOVR_ES;
/* note the lack of DECODE_CLEAR_SEGOVR(r)
since, here is one of 4 opcode subroutines we do not
want to do this.
*/
}
/*opcode=0x27*/
static void i86op_daa(PC_ENV *m)
{
uint16 dbyte;
dbyte = m->R_AL;
if (ACCESS_FLAG(m,F_AF)|| (dbyte&0xf) > 9)
{
dbyte += 6;
if (dbyte&0x100)
SET_FLAG(m, F_CF);
SET_FLAG(m, F_AF);
}
else
CLEAR_FLAG(m, F_AF);
if (ACCESS_FLAG(m,F_CF) || (dbyte&0xf0) > 0x90)
{
dbyte += 0x60;
SET_FLAG(m, F_CF);
}
else
CLEAR_FLAG(m, F_CF);
m->R_AL = (uint8) dbyte;
CONDITIONAL_SET_FLAG((m->R_AL & 0x80),m,F_SF);
CONDITIONAL_SET_FLAG((m->R_AL == 0), m,F_ZF);
CONDITIONAL_SET_FLAG((parity_tab[m->R_AL]),m,F_PF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x28*/
static void i86op_sub_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = sub_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = sub_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = sub_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = sub_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x29*/
static void i86op_sub_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = sub_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = sub_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = sub_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = sub_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x2a*/
static void i86op_sub_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = sub_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = sub_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = sub_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = sub_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x2b*/
static void i86op_sub_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = sub_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = sub_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = sub_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = sub_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x2c*/
static void i86op_sub_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = sub_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x2d*/
static void i86op_sub_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = sub_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x2e*/
static void i86op_segovr_CS(PC_ENV *m)
{
m->sysmode |= SYSMODE_SEGOVR_CS;
/* note no DECODE_CLEAR_SEGOVER here. */
}
/*opcode=0x2f*/
static void i86op_das(PC_ENV *m)
{
uint16 dbyte;
dbyte = m->R_AL;
if ( ACCESS_FLAG(m,F_AF) || (dbyte&0xf) > 9)
{
dbyte -= 6;
if (dbyte&0x100) /* XXXXX --- this is WRONG */
SET_FLAG(m, F_CF);
SET_FLAG(m, F_AF);
}
else
CLEAR_FLAG(m, F_AF);
if (ACCESS_FLAG(m,F_CF) || (dbyte&0xf0) > 0x90)
{
dbyte -= 0x60;
SET_FLAG(m, F_CF);
}
else
CLEAR_FLAG(m, F_CF);
m->R_AL = (uint8) dbyte;
CONDITIONAL_SET_FLAG(m->R_AL & 0x80,m,F_SF);
CONDITIONAL_SET_FLAG(m->R_AL == 0,m,F_ZF);
CONDITIONAL_SET_FLAG(parity_tab[m->R_AL],m,F_PF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x30*/
static void i86op_xor_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = xor_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = xor_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
destval = xor_byte(m, destval, *srcreg);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = xor_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x31*/
static void i86op_xor_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = xor_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = xor_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destval = xor_word(m, destval, *srcreg);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = xor_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x32*/
static void i86op_xor_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = xor_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = xor_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = xor_byte(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = xor_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x33*/
static void i86op_xor_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = xor_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = xor_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = xor_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = xor_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x34*/
static void i86op_xor_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
m->R_AL = xor_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x35*/
static void i86op_xor_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
m->R_AX = xor_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x36*/
static void i86op_segovr_SS(PC_ENV *m)
{
m->sysmode |= SYSMODE_SEGOVR_SS;
/* no DECODE_CLEAR_SEGOVER ! */
}
/*opcode=0x37*/
static void i86op_aaa(PC_ENV *m)
{
if ( (m->R_AL & 0xf) > 0x9 || ACCESS_FLAG(m,F_AF))
{
m->R_AL += 0x6;
m->R_AH += 1;
SET_FLAG(m, F_AF);
SET_FLAG(m, F_CF);
}
else
{
CLEAR_FLAG(m, F_CF);
CLEAR_FLAG(m, F_AF);
}
m->R_AL &= 0xf;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x38*/
static void i86op_cmp_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
cmp_byte(m, destval, *srcreg);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
cmp_byte(m, destval, *srcreg);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
cmp_byte(m, destval, *srcreg);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
cmp_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x39*/
static void i86op_cmp_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
cmp_word(m, destval, *srcreg);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
cmp_word(m, destval, *srcreg);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
cmp_word(m, destval, *srcreg);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
cmp_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x3a*/
static void i86op_cmp_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
cmp_byte(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
cmp_byte(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
cmp_byte(m, * destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
cmp_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x3b*/
static void i86op_cmp_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
cmp_word(m, *destreg, srcval);
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
cmp_word(m, *destreg, srcval);
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
cmp_word(m, *destreg, srcval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
cmp_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x3c*/
static void i86op_cmp_byte_AL_IMM(PC_ENV *m)
{
uint8 srcval;
srcval = fetch_byte_imm(m);
cmp_byte(m, m->R_AL, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x3d*/
static void i86op_cmp_word_AX_IMM(PC_ENV *m)
{
uint16 srcval;
srcval = fetch_word_imm(m);
cmp_word(m, m->R_AX, srcval);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x3e*/
static void i86op_segovr_DS(PC_ENV *m)
{
m->sysmode |= SYSMODE_SEGOVR_DS;
/* NO DECODE_CLEAR_SEGOVR! */
}
/*opcode=0x3f*/
static void i86op_aas(PC_ENV *m)
{
/* ???? Check out the subtraction here. Will this ?ever? cause
the contents of R_AL or R_AH to be affected incorrectly since
they are being subtracted from *and* are unsigned.
Should put an assertion in here.
*/
if ( (m->R_AL & 0xf) > 0x9 || ACCESS_FLAG(m,F_AF))
{
m->R_AL -= 0x6;
m->R_AH -= 1;
SET_FLAG(m, F_AF);
SET_FLAG(m, F_CF);
}
else
{
CLEAR_FLAG(m, F_CF);
CLEAR_FLAG(m, F_AF);
}
m->R_AL &= 0xf;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x40*/
static void i86op_inc_AX(PC_ENV *m)
{
m->R_AX = inc_word(m,m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x41*/
static void i86op_inc_CX(PC_ENV *m)
{
m->R_CX = inc_word(m,m->R_CX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x42*/
static void i86op_inc_DX(PC_ENV *m)
{
m->R_DX = inc_word(m,m->R_DX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x43*/
static void i86op_inc_BX(PC_ENV *m)
{
m->R_BX = inc_word(m,m->R_BX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x44*/
static void i86op_inc_SP(PC_ENV *m)
{
m->R_SP = inc_word(m,m->R_SP);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x45*/
static void i86op_inc_BP(PC_ENV *m)
{
m->R_BP = inc_word(m,m->R_BP);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x46*/
static void i86op_inc_SI(PC_ENV *m)
{
m->R_SI = inc_word(m,m->R_SI);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x47*/
static void i86op_inc_DI(PC_ENV *m)
{
m->R_DI = inc_word(m,m->R_DI);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x48*/
static void i86op_dec_AX(PC_ENV *m)
{
m->R_AX = dec_word(m,m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x49*/
static void i86op_dec_CX(PC_ENV *m)
{
m->R_CX = dec_word(m,m->R_CX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x4a*/
static void i86op_dec_DX(PC_ENV *m)
{
m->R_DX = dec_word(m,m->R_DX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x4b*/
static void i86op_dec_BX(PC_ENV *m)
{
m->R_BX = dec_word(m,m->R_BX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x4c*/
static void i86op_dec_SP(PC_ENV *m)
{
m->R_SP = dec_word(m,m->R_SP);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x4d*/
static void i86op_dec_BP(PC_ENV *m)
{
m->R_BP = dec_word(m,m->R_BP);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x4e*/
static void i86op_dec_SI(PC_ENV *m)
{
m->R_SI = dec_word(m,m->R_SI);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x4f*/
static void i86op_dec_DI(PC_ENV *m)
{
m->R_DI = dec_word(m,m->R_DI);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x50*/
static void i86op_push_AX(PC_ENV *m)
{
push_word(m,m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x51*/
static void i86op_push_CX(PC_ENV *m)
{
push_word(m,m->R_CX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x52*/
static void i86op_push_DX(PC_ENV *m)
{
push_word(m,m->R_DX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x53*/
static void i86op_push_BX(PC_ENV *m)
{
push_word(m,m->R_BX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x54*/
static void i86op_push_SP(PC_ENV *m)
{
/* .... Note this weirdness: One book I have access to
claims that the value pushed here is actually sp-2. I.e.
it decrements the stackpointer, and then pushes it. The 286
I have does it this way. Changing this causes many problems.*/
/* changed to push SP-2, since this *IS* how a 8088 does this */
push_word(m,m->R_SP-2);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x55*/
static void i86op_push_BP(PC_ENV *m)
{
push_word(m,m->R_BP);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x56*/
static void i86op_push_SI(PC_ENV *m)
{
push_word(m,m->R_SI);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x57*/
static void i86op_push_DI(PC_ENV *m)
{
push_word(m,m->R_DI);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x58*/
static void i86op_pop_AX(PC_ENV *m)
{
m->R_AX = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x59*/
static void i86op_pop_CX(PC_ENV *m)
{
m->R_CX = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x5a*/
static void i86op_pop_DX(PC_ENV *m)
{
m->R_DX = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x5b*/
static void i86op_pop_BX(PC_ENV *m)
{
m->R_BX = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x5c*/
static void i86op_pop_SP(PC_ENV *m)
{
m->R_SP = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x5d*/
static void i86op_pop_BP(PC_ENV *m)
{
m->R_BP = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x5e*/
static void i86op_pop_SI(PC_ENV *m)
{
m->R_SI = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x5f*/
static void i86op_pop_DI(PC_ENV *m)
{
m->R_DI = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x60 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x61 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x62 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x63 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x64 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x65 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x66 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x67 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x68 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x69 ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x6a ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x6b ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x6c ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x6d ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x6e ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x6f ILLEGAL OP, calls i86op_illegal_op() */
/*opcode=0x70*/
static void i86op_jump_near_O(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if overflow flag is set */
offset = (int8) fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (ACCESS_FLAG(m,F_OF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x71*/
static void i86op_jump_near_NO(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if overflow is not set */
offset = (int8) fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (!ACCESS_FLAG(m,F_OF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x72*/
static void i86op_jump_near_B(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if carry flag is set. */
offset = (int8)fetch_byte_imm(m); /* sign extended ??? */
target = (int16)(m->R_IP) + offset;
if (ACCESS_FLAG(m, F_CF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x73*/
static void i86op_jump_near_NB(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if carry flag is clear. */
offset = (int8)fetch_byte_imm(m); /* sign extended ??? */
target = (int16)(m->R_IP) + offset;
if (!ACCESS_FLAG(m,F_CF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x74*/
static void i86op_jump_near_Z(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if zero flag is set. */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (ACCESS_FLAG(m, F_ZF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x75*/
static void i86op_jump_near_NZ(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if zero flag is clear. */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (!ACCESS_FLAG(m, F_ZF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x76*/
static void i86op_jump_near_BE(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if carry flag is set or if the zero
flag is set. */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (ACCESS_FLAG(m,F_CF) || ACCESS_FLAG(m,F_ZF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x77*/
static void i86op_jump_near_NBE(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if carry flag is clear and if the zero
flag is clear */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (!(ACCESS_FLAG(m,F_CF)||ACCESS_FLAG(m,F_ZF)))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x78*/
static void i86op_jump_near_S(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if sign flag is set */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (ACCESS_FLAG(m,F_SF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x79*/
static void i86op_jump_near_NS(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if sign flag is clear */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (!ACCESS_FLAG(m,F_SF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x7a*/
static void i86op_jump_near_P(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if parity flag is set (even parity) */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (ACCESS_FLAG(m, F_PF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x7b*/
static void i86op_jump_near_NP(PC_ENV *m)
{
int8 offset;
uint16 target;
/* jump to byte offset if parity flag is clear (odd parity) */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
if (!ACCESS_FLAG(m, F_PF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/* JHH fixed till here... */
/*opcode=0x7c*/
static void i86op_jump_near_L(PC_ENV *m)
{
int8 offset;
uint16 target;
int sf,of;
/* jump to byte offset if sign flag not equal to overflow flag. */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
/* note:
* this is the simplest expression i could think of which
* expresses SF != OF. m->R_FLG&F_SF either equals x80 or x00.
* Similarly m->R_FLG&F_OF either equals x800 or x000.
* The former shifted right by 7 puts a 1 or 0 in bit 0.
* The latter shifter right by 11 puts a 1 or 0 in bit 0.
* if the two expressions are the same, i.e. equal, then
* a zero results from the xor. If they are not equal,
* then a 1 results, and the jump is taken.
*/
sf = ACCESS_FLAG(m,F_SF) != 0;
of = ACCESS_FLAG(m,F_OF) != 0;
/* was: if ( ((m->R_FLG & F_SF)>>7) ^ ((m->R_FLG & F_OF) >> 11))*/
if (sf ^ of)
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x7d*/
static void i86op_jump_near_NL(PC_ENV *m)
{
int8 offset;
uint16 target;
int sf,of;
/* jump to byte offset if sign flag not equal to overflow flag. */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
sf = ACCESS_FLAG(m,F_SF) != 0;
of = ACCESS_FLAG(m,F_OF) != 0;
/* note: inverse of above, but using == instead of xor. */
/* was: if (((m->R_FLG & F_SF)>>7) == ((m->R_FLG & F_OF) >> 11))*/
if (sf == of)
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x7e*/
static void i86op_jump_near_LE(PC_ENV *m)
{
int8 offset;
uint16 target;
int sf,of;
/* jump to byte offset if sign flag not equal to overflow flag
or the zero flag is set */
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
sf = ACCESS_FLAG(m,F_SF) != 0;
of = ACCESS_FLAG(m,F_OF) != 0;
/* note: modification of JL */
/* sf != of */
/* was: if ((((m->R_FLG & F_SF)>>7) ^ ((m->R_FLG & F_OF) >> 11))
|| (m->R_FLG & F_ZF) ) */
if ( (sf ^ of) || ACCESS_FLAG(m,F_ZF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x7f*/
static void i86op_jump_near_NLE(PC_ENV *m)
{
int8 offset;
uint16 target;
int sf,of;
/* jump to byte offset if sign flag equal to overflow flag.
and the zero flag is clear*/
offset = (int8)fetch_byte_imm(m);
target = (int16)(m->R_IP) + offset;
sf = ACCESS_FLAG(m,F_SF) != 0;
of = ACCESS_FLAG(m,F_OF) != 0;
/* if (((m->R_FLG & F_SF)>>7) == ((m->R_FLG & F_OF) >> 11)
&& (!(m->R_FLG & F_ZF))) */
if ( ( sf == of ) && !ACCESS_FLAG(m,F_ZF))
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
static uint8 (*opc80_byte_operation[])(PC_ENV *m,uint8 d,uint8 s) =
{
add_byte,/*00*/
or_byte, /*01*/
adc_byte,/*02*/
sbb_byte,/*03*/
and_byte,/*04*/
sub_byte,/*05*/
xor_byte,/*06*/
cmp_byte,/*07*/
};
/*opcode=0x80*/
static void i86op_opc80_byte_RM_IMM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg;
uint16 destoffset;
uint8 imm;
uint8 destval;
/* weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imm = fetch_byte_imm(m);
destval = (*opc80_byte_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imm = fetch_byte_imm(m);
destval = (*opc80_byte_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imm = fetch_byte_imm(m);
destval = (*opc80_byte_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
imm = fetch_byte_imm(m);
destval = (*opc80_byte_operation[rh])(m, *destreg, imm);
if (rh != 7)
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
static uint16 (*opc81_word_operation[])(PC_ENV *m,uint16 d,uint16 s) =
{ add_word,/*00*/
or_word, /*01*/
adc_word,/*02*/
sbb_word,/*03*/
and_word,/*04*/
sub_word,/*05*/
xor_word,/*06*/
cmp_word,/*07*/
};
/*opcode=0x81*/
static void i86op_opc81_word_RM_IMM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 imm;
uint16 destval;
/* weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
imm = fetch_word_imm(m);
destval = (*opc81_word_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
imm = fetch_word_imm(m);
destval = (*opc81_word_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
imm = fetch_word_imm(m);
destval = (*opc81_word_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
imm = fetch_word_imm(m);
destval = (*opc81_word_operation[rh])(m, *destreg, imm);
if (rh != 7)
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
static uint8 (*opc82_byte_operation[])(PC_ENV *m,uint8 s,uint8 d) =
{
add_byte,/*00*/
or_byte, /*01*/ /*YYY UNUSED ????*/
adc_byte,/*02*/
sbb_byte,/*03*/
and_byte,/*04*/ /*YYY UNUSED ????*/
sub_byte,/*05*/
xor_byte,/*06*/ /*YYY UNUSED ????*/
cmp_byte,/*07*/
};
/*opcode=0x82*/
static void i86op_opc82_byte_RM_IMM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg;
uint16 destoffset;
uint8 imm;
uint8 destval;
/* weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
Similar to opcode 81, except that the immediate byte
is sign extended to a word length.
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imm = fetch_byte_imm(m);
destval = (*opc82_byte_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imm = fetch_byte_imm(m);
destval = (*opc82_byte_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imm = fetch_byte_imm(m);
destval = (*opc82_byte_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
imm = fetch_byte_imm(m);
destval = (*opc82_byte_operation[rh])(m, *destreg, imm);
if (rh != 7)
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
static uint16 (*opc83_word_operation[])(PC_ENV *m,uint16 s,uint16 d) =
{
add_word,/*00*/
or_word, /*01*/ /*YYY UNUSED ????*/
adc_word,/*02*/
sbb_word,/*03*/
and_word,/*04*/ /*YYY UNUSED ????*/
sub_word,/*05*/
xor_word,/*06*/ /*YYY UNUSED ????*/
cmp_word,/*07*/
};
/*opcode=0x83*/
static void i86op_opc83_word_RM_IMM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 imm;
uint16 destval;
/* weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
Similar to opcode 81, except that the immediate byte
is sign extended to a word length.
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
imm = (int8)fetch_byte_imm(m);
destval = (*opc83_word_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
imm = (int8)fetch_byte_imm(m);
destval = (*opc83_word_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
imm = (int8) fetch_byte_imm(m);
destval = (*opc83_word_operation[rh])(m, destval, imm);
if (rh != 7)
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
imm = (int8) fetch_byte_imm(m);
destval = (*opc83_word_operation[rh])(m, *destreg, imm);
if (rh != 7)
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x84*/
static void i86op_test_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
test_byte(m, destval, *srcreg);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
test_byte(m, destval, *srcreg);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
test_byte(m, destval, *srcreg);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
test_byte(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x85*/
static void i86op_test_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
test_word(m, destval, *srcreg);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
test_word(m, destval, *srcreg);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
test_word(m, destval, *srcreg);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
test_word(m, *destreg, *srcreg);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x86*/
static void i86op_xchg_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
uint8 destval;
uint8 tmp;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = destval;
destval = tmp;
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = destval;
destval = tmp;
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = destval;
destval = tmp;
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = *destreg;
*destreg = tmp;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x87*/
static void i86op_xchg_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
uint16 tmp;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = destval;
destval = tmp;
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = destval;
destval = tmp;
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = destval;
destval = tmp;
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
tmp = *srcreg;
*srcreg = *destreg;
*destreg = tmp;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x88*/
static void i86op_mov_byte_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 destoffset;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
store_data_byte(m,destoffset,*srcreg);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
store_data_byte(m,destoffset,*srcreg);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
store_data_byte(m,destoffset,*srcreg);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
*destreg = *srcreg;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x89*/
static void i86op_mov_word_RM_R(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
store_data_word(m,destoffset,*srcreg);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
store_data_word(m,destoffset,*srcreg);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
store_data_word(m,destoffset,*srcreg);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
*destreg = *srcreg;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x8a*/
static void i86op_mov_byte_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg,*srcreg;
uint16 srcoffset;
uint8 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = srcval;
break;
case 1:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = srcval;
break;
case 2:
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_byte(m,srcoffset);
*destreg = srcval;
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rh);
srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = *srcreg;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x8b*/
static void i86op_mov_word_R_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = srcval;
break;
case 1:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = srcval;
break;
case 2:
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = srcval;
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = *srcreg;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x8c*/
static void i86op_mov_word_RM_SR(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
srcreg = decode_rm_seg_register(m,rh);
destval = *srcreg;
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
srcreg = decode_rm_seg_register(m,rh);
destval = *srcreg;
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
srcreg = decode_rm_seg_register(m,rh);
destval = *srcreg;
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
srcreg = decode_rm_seg_register(m,rh);
*destreg = *srcreg;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x8d*/
static void i86op_lea_word_R_M(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *srcreg;
uint16 destoffset;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destoffset=decode_rm00_address(m,rl);
*srcreg = destoffset;
break;
case 1:
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destoffset=decode_rm01_address(m,rl);
*srcreg = destoffset;
break;
case 2:
srcreg = DECODE_RM_WORD_REGISTER(m,rh);
destoffset=decode_rm10_address(m,rl);
*srcreg = destoffset;
break;
case 3: /* register to register */
/* undefined. Do nothing. */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x8e*/
static void i86op_mov_word_SR_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg,*srcreg;
uint16 srcoffset;
uint16 srcval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destreg = decode_rm_seg_register(m,rh);
srcoffset=decode_rm00_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = srcval;
break;
case 1:
destreg = decode_rm_seg_register(m,rh);
srcoffset=decode_rm01_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = srcval;
break;
case 2:
destreg = decode_rm_seg_register(m,rh);
srcoffset = decode_rm10_address(m,rl);
srcval = fetch_data_word(m,srcoffset);
*destreg = srcval;
break;
case 3: /* register to register */
destreg = decode_rm_seg_register(m,rh);
srcreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = *srcreg;
break;
}
/*\
* clean up, and reset all the R_xSP pointers to the correct
* locations. This is about 3x too much overhead (doing all the
* segreg ptrs when only one is needed, but this instruction
* *cannot* be that common, and this isn't too much work anyway.
\*/
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x8f*/
static void i86op_pop_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 destval;
FETCH_DECODE_MODRM(m,mod,rh,rl);
if (rh != 0)
{
halt_sys(m);
}
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = pop_word( m);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = pop_word(m);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = pop_word(m);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = pop_word(m);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x90*/
static void i86op_nop(PC_ENV *m)
{
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x91*/
static void i86op_xchg_word_AX_CX(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_CX;
m->R_CX = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x92*/
static void i86op_xchg_word_AX_DX(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_DX;
m->R_DX = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x93*/
static void i86op_xchg_word_AX_BX(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_BX;
m->R_BX = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x94*/
static void i86op_xchg_word_AX_SP(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_SP;
m->R_SP = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x95*/
static void i86op_xchg_word_AX_BP(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_BP;
m->R_BP = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x96*/
static void i86op_xchg_word_AX_SI(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_SI;
m->R_SI = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x97*/
static void i86op_xchg_word_AX_DI(PC_ENV *m)
{
uint16 tmp;
tmp = m->R_AX;
m->R_AX = m->R_DI;
m->R_DI = tmp;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x98*/
static void i86op_cbw(PC_ENV *m)
{
if (m->R_AL & 0x80)
{
m->R_AH = 0xff;
}
else
{
m->R_AH = 0x0;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x99*/
static void i86op_cwd(PC_ENV *m)
{
if (m->R_AX & 0x8000)
{
m->R_DX = 0xffff;
}
else
{
m->R_DX = 0x0;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x9a*/
static void i86op_call_far_IMM(PC_ENV *m)
{
uint16 farseg,faroff;
faroff = fetch_word_imm(m);
farseg = fetch_word_imm(m);
/* XXX
HOOKED INTERRUPT VECTORS CALLING INTO OUR "BIOS"
WILL CAUSE PROBLEMS UNLESS ALL INTERSEGMENT STUFF IS
CHECKED FOR BIOS ACCESS. CHECK NEEDED HERE.
FOR MOMENT, LET IT ALONE.
*/
push_word(m,m->R_CS);
m->R_CS = farseg;
push_word(m,m->R_IP);
m->R_IP = faroff;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x9b*/
static void i86op_wait(PC_ENV *m)
{
/* NADA. */
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x9c*/
static void i86op_pushf_word(PC_ENV *m)
{
uint16 flags;
flags = m->R_FLG;
/* clear out *all* bits not representing flags */
flags &= F_MSK;
/* TURN ON CHARACTERISTIC BITS OF FLAG FOR 8088 */
flags |= F_ALWAYS_ON;
push_word(m,flags);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x9d*/
static void i86op_popf_word(PC_ENV *m)
{
m->R_FLG = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x9e*/
static void i86op_sahf(PC_ENV *m)
{
/* clear the lower bits of the flag register */
m->R_FLG &= 0xffffff00;
/* or in the AH register into the flags register */
m->R_FLG |= m->R_AH;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0x9f*/
static void i86op_lahf(PC_ENV *m)
{
m->R_AH = m->R_FLG & 0xff;
/*undocumented TC++ behavior??? Nope. It's documented, but
you have too look real hard to notice it. */
m->R_AH |= 0x2;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa0*/
static void i86op_mov_AL_M_IMM(PC_ENV *m)
{
uint16 offset;
uint8 destval;
offset = fetch_word_imm(m);
destval = fetch_data_byte(m,offset);
m->R_AL = destval;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa1*/
static void i86op_mov_AX_M_IMM(PC_ENV *m)
{
uint16 offset;
uint16 destval;
offset = fetch_word_imm(m);
destval = fetch_data_word(m,offset);
m->R_AX = destval;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa2*/
static void i86op_mov_M_AL_IMM(PC_ENV *m)
{
uint16 offset;
offset = fetch_word_imm(m);
store_data_byte(m,offset,m->R_AL);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa3*/
static void i86op_mov_M_AX_IMM(PC_ENV *m)
{
uint16 offset;
offset = fetch_word_imm(m);
store_data_word(m,offset,m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/* JHH CLEANED */
/*opcode=0xa4*/
static void i86op_movs_byte(PC_ENV *m)
{
uint8 val;
int inc;
if (ACCESS_FLAG(m,F_DF)) /* down */
inc = -1;
else
inc = 1;
if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
{
/* dont care whether REPE or REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val = fetch_data_byte(m,m->R_SI);
store_data_byte_abs(m,m->R_ES,m->R_DI,val);
m->R_CX -= 1;
m->R_SI += inc;
m->R_DI += inc;
}
m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
else
{
val = fetch_data_byte(m,m->R_SI);
store_data_byte_abs(m,m->R_ES,m->R_DI,val);
m->R_SI += inc;
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa5*/
static void i86op_movs_word(PC_ENV *m)
{
int16 val;
int inc;
if (ACCESS_FLAG(m, F_DF)) /* down */
inc = -2;
else
inc = 2;
if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
{
/* dont care whether REPE or REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val = fetch_data_word(m,m->R_SI);
store_data_word_abs(m,m->R_ES,m->R_DI,val);
m->R_CX -= 1;
m->R_SI += inc;
m->R_DI += inc;
}
m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
else
{
val = fetch_data_word(m,m->R_SI);
store_data_word_abs(m,m->R_ES,m->R_DI,val);
m->R_SI += inc;
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa6*/
static void i86op_cmps_byte(PC_ENV *m)
{
int8 val1,val2;
int inc;
if (ACCESS_FLAG(m,F_DF)) /* down */
inc = -1;
else
inc = 1;
if (m->sysmode & SYSMODE_PREFIX_REPE)
{
/* REPE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val1 = fetch_data_byte(m,m->R_SI);
val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
cmp_byte(m, val1,val2);
m->R_CX -= 1;
m->R_SI += inc;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF)==0)
break;
}
m->sysmode &= ~SYSMODE_PREFIX_REPE;
}
else if (m->sysmode & SYSMODE_PREFIX_REPNE)
{
/* REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val1 = fetch_data_byte(m,m->R_SI);
val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
cmp_byte(m, val1,val2);
m->R_CX -= 1;
m->R_SI += inc;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF))
break; /* zero flag set means equal */
}
m->sysmode &= ~SYSMODE_PREFIX_REPNE;
}
else
{
val1 = fetch_data_byte(m,m->R_SI);
val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
cmp_byte(m, val1,val2);
m->R_SI += inc;
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa7*/
static void i86op_cmps_word(PC_ENV *m)
{
int16 val1,val2;
int inc;
if (ACCESS_FLAG(m,F_DF)) /* down */
inc = -2;
else
inc = 2;
if (m->sysmode & SYSMODE_PREFIX_REPE)
{
/* REPE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val1 = fetch_data_word(m,m->R_SI);
val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
cmp_word(m, val1,val2);
m->R_CX -= 1;
m->R_SI += inc;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF)==0)
break;
}
m->sysmode &= ~SYSMODE_PREFIX_REPE;
}
else if (m->sysmode & SYSMODE_PREFIX_REPNE)
{
/* REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val1 = fetch_data_word(m,m->R_SI);
val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
cmp_word(m, val1,val2);
m->R_CX -= 1;
m->R_SI += inc;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF))
break; /* zero flag set means equal */
}
m->sysmode &= ~SYSMODE_PREFIX_REPNE;
}
else
{
val1 = fetch_data_word(m,m->R_SI);
val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
cmp_word(m, val1,val2);
m->R_SI += inc;
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa8*/
static void i86op_test_AL_IMM(PC_ENV *m)
{
int imm;
imm = fetch_byte_imm(m);
test_byte(m, m->R_AL, imm);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xa9*/
static void i86op_test_AX_IMM(PC_ENV *m)
{
int imm;
imm = fetch_word_imm(m);
test_word(m, m->R_AX, imm);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xaa*/
static void i86op_stos_byte(PC_ENV *m)
{
int inc;
if (ACCESS_FLAG(m, F_DF)) /* down */
inc = -1;
else
inc = 1;
if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
{
/* dont care whether REPE or REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
store_data_byte_abs(m,m->R_ES,m->R_DI,m->R_AL);
m->R_CX -= 1;
m->R_DI += inc;
}
m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
else
{
store_data_byte_abs(m,m->R_ES,m->R_DI,m->R_AL);
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xab*/
static void i86op_stos_word(PC_ENV *m)
{
int inc;
if (ACCESS_FLAG(m, F_DF)) /* down */
inc = -2;
else
inc = 2;
if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
{
/* dont care whether REPE or REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
store_data_word_abs(m,m->R_ES,m->R_DI,m->R_AX);
m->R_CX -= 1;
m->R_DI += inc;
}
m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
else
{
store_data_word_abs(m,m->R_ES,m->R_DI,m->R_AX);
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xac*/
static void i86op_lods_byte(PC_ENV *m)
{
int inc;
if (ACCESS_FLAG(m,F_DF)) /* down */
inc = -1;
else
inc = 1;
if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
{
/* dont care whether REPE or REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
m->R_AL = fetch_data_byte(m,m->R_SI);
m->R_CX -= 1;
m->R_SI += inc;
}
m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
else
{
m->R_AL = fetch_data_byte(m,m->R_SI);
m->R_SI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xad*/
static void i86op_lods_word(PC_ENV *m)
{
int inc;
if (ACCESS_FLAG(m,F_DF)) /* down */
inc = -2;
else
inc = 2;
if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
{
/* dont care whether REPE or REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
m->R_AX = fetch_data_word(m,m->R_SI);
m->R_CX -= 1;
m->R_SI += inc;
}
m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
else
{
m->R_AX = fetch_data_word(m,m->R_SI);
m->R_SI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xae*/
static void i86op_scas_byte(PC_ENV *m)
{
int8 val2;
int inc;
if (ACCESS_FLAG(m,F_DF)) /* down */
inc = -1;
else
inc = 1;
if (m->sysmode & SYSMODE_PREFIX_REPE)
{
/* REPE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
cmp_byte(m, m->R_AL,val2);
m->R_CX -= 1;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF)==0)
break;
}
m->sysmode &= ~SYSMODE_PREFIX_REPE;
}
else if (m->sysmode & SYSMODE_PREFIX_REPNE)
{
/* REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
cmp_byte(m, m->R_AL,val2);
m->R_CX -= 1;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF))
break; /* zero flag set means equal */
}
m->sysmode &= ~SYSMODE_PREFIX_REPNE;
}
else
{
val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
cmp_byte(m, m->R_AL,val2);
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xaf*/
static void i86op_scas_word(PC_ENV *m)
{
int16 val2;
int inc;
if (ACCESS_FLAG(m, F_DF)) /* down */
inc = -2;
else
inc = 2;
if (m->sysmode & SYSMODE_PREFIX_REPE)
{
/* REPE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
cmp_word(m,m->R_AX,val2);
m->R_CX -= 1;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF)==0)
break;
}
m->sysmode &= ~SYSMODE_PREFIX_REPE;
}
else if (m->sysmode & SYSMODE_PREFIX_REPNE)
{
/* REPNE */
/* move them until CX is ZERO. */
while (m->R_CX != 0)
{
val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
cmp_word(m, m->R_AX,val2);
m->R_CX -= 1;
m->R_DI += inc;
if (ACCESS_FLAG(m,F_ZF))
break; /* zero flag set means equal */
}
m->sysmode &= ~SYSMODE_PREFIX_REPNE;
}
else
{
val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
cmp_word(m, m->R_AX,val2);
m->R_DI += inc;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb0*/
static void i86op_mov_byte_AL_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_AL = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb1*/
static void i86op_mov_byte_CL_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_CL = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb2*/
static void i86op_mov_byte_DL_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_DL = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb3*/
static void i86op_mov_byte_BL_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_BL = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb4*/
static void i86op_mov_byte_AH_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_AH = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb5*/
static void i86op_mov_byte_CH_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_CH = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb6*/
static void i86op_mov_byte_DH_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_DH = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb7*/
static void i86op_mov_byte_BH_IMM(PC_ENV *m)
{
uint8 imm;
imm = fetch_byte_imm(m);
m->R_BH = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb8*/
static void i86op_mov_word_AX_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_AX = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xb9*/
static void i86op_mov_word_CX_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_CX = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xba*/
static void i86op_mov_word_DX_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_DX = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xbb*/
static void i86op_mov_word_BX_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_BX = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xbc*/
static void i86op_mov_word_SP_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_SP = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xbd*/
static void i86op_mov_word_BP_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_BP = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xbe*/
static void i86op_mov_word_SI_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_SI = imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xbf*/
static void i86op_mov_word_DI_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_DI = imm;
DECODE_CLEAR_SEGOVR(m);
}
/* c0 === ILLEGAL OPERAND */
/* c1 === ILLEGAL OPERAND */
/*opcode=0xc2*/
static void i86op_ret_near_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_IP = pop_word(m);
m->R_SP += imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xc3*/
static void i86op_ret_near(PC_ENV *m)
{
m->R_IP = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xc4*/
static void i86op_les_R_IMM(PC_ENV *m)
{
uint16 mod,rh,rl;
uint16 *dstreg;
uint16 srcoffset;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
dstreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
*dstreg = fetch_data_word(m,srcoffset);
m->R_ES = fetch_data_word(m,srcoffset+2);
break;
case 1:
dstreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
*dstreg = fetch_data_word(m,srcoffset);
m->R_ES = fetch_data_word(m,srcoffset+2);
break;
case 2:
dstreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
*dstreg = fetch_data_word(m,srcoffset);
m->R_ES = fetch_data_word(m,srcoffset+2);
break;
case 3: /* register to register */
/* UNDEFINED! */
;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xc5*/
static void i86op_lds_R_IMM(PC_ENV *m)
{
uint16 mod,rh,rl;
uint16 *dstreg;
uint16 srcoffset;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
dstreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm00_address(m,rl);
*dstreg = fetch_data_word(m,srcoffset);
m->R_DS = fetch_data_word(m,srcoffset+2);
break;
case 1:
dstreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm01_address(m,rl);
*dstreg = fetch_data_word(m,srcoffset);
m->R_DS = fetch_data_word(m,srcoffset+2);
break;
case 2:
dstreg = DECODE_RM_WORD_REGISTER(m,rh);
srcoffset=decode_rm10_address(m,rl);
*dstreg = fetch_data_word(m,srcoffset);
m->R_DS = fetch_data_word(m,srcoffset+2);
break;
case 3: /* register to register */
/* UNDEFINED! */
;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xc6*/
static void i86op_mov_byte_RM_IMM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg;
uint16 destoffset;
uint8 imm;
FETCH_DECODE_MODRM(m,mod,rh,rl);
if (rh != 0)
{
halt_sys(m);
}
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
imm = fetch_byte_imm(m);
store_data_byte(m,destoffset,imm);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
imm = fetch_byte_imm(m);
store_data_byte(m,destoffset,imm);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
imm = fetch_byte_imm(m);
store_data_byte(m,destoffset,imm);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
imm = fetch_byte_imm(m);
*destreg = imm;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xc7*/
static void i86op_mov_word_RM_IMM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 imm;
FETCH_DECODE_MODRM(m,mod,rh,rl);
if (rh != 0)
{
halt_sys(m);
}
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
imm = fetch_word_imm(m);
store_data_word(m,destoffset,imm);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
imm = fetch_word_imm(m);
store_data_word(m,destoffset,imm);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
imm = fetch_word_imm(m);
store_data_word(m,destoffset,imm);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
imm = fetch_word_imm(m);
*destreg = imm;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xc8 ILLEGAL OP*/
/*opcode=0xc9 ILLEGAL OP*/
/*opcode=0xca*/
static void i86op_ret_far_IMM(PC_ENV *m)
{
uint16 imm;
imm = fetch_word_imm(m);
m->R_IP = pop_word(m);
m->R_CS = pop_word(m);
m->R_SP += imm;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xcb*/
static void i86op_ret_far(PC_ENV *m)
{
m->R_IP = pop_word(m);
m->R_CS = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xcc*/
static void i86op_int3(PC_ENV *m)
{
uint16 tmp;
/* access the segment register */
{
tmp = m->R_FLG;
push_word(m, tmp);
CLEAR_FLAG(m, F_IF);
CLEAR_FLAG(m, F_TF);
/* [JCE] If we're interrupting between a segment override (or REP override)
* and the following instruction, decrease IP to get back to the prefix */
if (m->sysmode & (SYSMODE_SEGMASK |
SYSMODE_PREFIX_REPE |
SYSMODE_PREFIX_REPNE))
{
--m->R_IP;
}
push_word(m, m->R_CS);
push_word(m, m->R_IP);
/* [JCE] CS and IP were the wrong way round... */
tmp = mem_access_word(m, 3 * 4);
m->R_IP = tmp;
tmp = mem_access_word(m, 3 * 4 + 2);
m->R_CS = tmp;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xcd*/
static void i86op_int_IMM(PC_ENV *m)
{
uint16 tmp;
uint8 intnum;
intnum = fetch_byte_imm(m);
{
tmp = m->R_FLG;
push_word(m, tmp);
CLEAR_FLAG(m, F_IF);
CLEAR_FLAG(m, F_TF);
/* [JCE] If we're interrupting between a segment override (or REP override)
* and the following instruction, decrease IP to get back to the prefix */
if (m->sysmode & (SYSMODE_SEGMASK |
SYSMODE_PREFIX_REPE |
SYSMODE_PREFIX_REPNE))
{
--m->R_IP;
}
push_word(m, m->R_CS);
push_word(m, m->R_IP);
/* [JCE] CS and IP were the wrong way round... */
tmp = mem_access_word(m, intnum * 4);
m->R_IP = tmp;
tmp = mem_access_word(m, intnum * 4 + 2);
m->R_CS = tmp;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xce*/
static void i86op_into(PC_ENV *m)
{
uint16 tmp;
if (ACCESS_FLAG(m,F_OF))
{
{
tmp = m->R_FLG;
push_word(m, tmp);
CLEAR_FLAG(m, F_IF);
CLEAR_FLAG(m, F_TF);
/* [JCE] If we're interrupting between a segment override (or REP override)
* and the following instruction, decrease IP to get back to the prefix */
if (m->sysmode & (SYSMODE_SEGMASK |
SYSMODE_PREFIX_REPE |
SYSMODE_PREFIX_REPNE))
{
--m->R_IP;
}
push_word(m, m->R_CS);
push_word(m, m->R_IP);
/* [JCE] CS and IP were the wrong way round... */
tmp = mem_access_word(m, 4 * 4);
m->R_IP = tmp;
tmp = mem_access_word(m, 4 * 4 + 2);
m->R_CS = tmp;
}
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xcf*/
static void i86op_iret(PC_ENV *m)
{
m->R_IP = pop_word(m);
m->R_CS = pop_word(m);
m->R_FLG = pop_word(m);
DECODE_CLEAR_SEGOVR(m);
}
static uint8 (*opcD0_byte_operation[])(PC_ENV *m,uint8 d, uint8 s) =
/* used by opcodes d0 and d2. */
{
rol_byte,
ror_byte,
rcl_byte,
rcr_byte,
shl_byte,
shr_byte,
shl_byte, /* sal_byte === shl_byte by definition */
sar_byte,
};
/* opcode=0xd0*/
static void i86op_opcD0_byte_RM_1(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg;
uint16 destoffset;
uint8 destval;
/* Yet another weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = (*opcD0_byte_operation[rh])(m, destval,1);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = (*opcD0_byte_operation[rh])(m, destval, 1);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = (*opcD0_byte_operation[rh])(m, destval, 1);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
destval = (*opcD0_byte_operation[rh])(m, *destreg, 1);
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
static uint16 (*opcD1_word_operation[])(PC_ENV *m,uint16 s,uint16 d) =
/* used by opcodes d1 and d3. */
{ rol_word,
ror_word,
rcl_word,
rcr_word,
shl_word,
shr_word,
shl_word, /* sal_byte === shl_byte by definition */
sar_word,
};
/* opcode=0xd1*/
static void i86op_opcD1_word_RM_1(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 destval;
/* Yet another weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = (*opcD1_word_operation[rh])(m, destval,1);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = (*opcD1_word_operation[rh])(m, destval, 1);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = (*opcD1_word_operation[rh])(m, destval, 1);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
destval = (*opcD1_word_operation[rh])(m, *destreg, 1);
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xd2*/
static void i86op_opcD2_byte_RM_CL(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg;
uint16 destoffset;
uint8 destval;
uint8 amt;
/* Yet another weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
amt = m->R_CL;
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = (*opcD0_byte_operation[rh])(m, destval,amt);
store_data_byte(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = (*opcD0_byte_operation[rh])(m, destval, amt);
store_data_byte(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = (*opcD0_byte_operation[rh])(m, destval, amt);
store_data_byte(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
destval = (*opcD0_byte_operation[rh])(m, *destreg, amt);
*destreg = destval;
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xd3*/
static void i86op_opcD3_word_RM_CL(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 destval;
uint8 amt;
/* Yet another weirdo special case instruction format. Part of the
opcode held below in "RH". Doubly nested case would
result, except that the decoded instruction
*/
FETCH_DECODE_MODRM(m,mod,rh,rl);
amt = m->R_CL;
/* know operation, decode the mod byte to find the addressing
mode. */
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = (*opcD1_word_operation[rh])(m, destval, amt);
store_data_word(m,destoffset,destval);
break;
case 1:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = (*opcD1_word_operation[rh])(m, destval, amt);
store_data_word(m,destoffset,destval);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = (*opcD1_word_operation[rh])(m, destval, amt);
store_data_word(m,destoffset,destval);
break;
case 3: /* register to register */
destreg = DECODE_RM_WORD_REGISTER(m,rl);
*destreg = (*opcD1_word_operation[rh])(m, *destreg, amt);
break;
}
DECODE_CLEAR_SEGOVR(m);
}
static void sys_fatal(int error, char *fmt, ...)
{
va_list p;
va_start(p, fmt);
fprintf(stderr, "Fatal error: ");
if (error != 0)
{
fprintf(stderr, "<%d>",error);
fprintf(stderr,"%s",strerror(error));
}
vfprintf(stderr, fmt, p);
va_end(p);
fprintf(stderr, NLP "Exiting..." NLP);
exit(1);
}
/* opcode=0xd4*/
static void i86op_aam(PC_ENV *m)
{ uint8 a;
a = fetch_byte_imm(m); /* this is a stupid encoding. */
if (a != 10)
sys_fatal(0,"error decoding aam" NLP);
/* note the type change here --- returning AL and AH in AX. */
m->R_AX = aam_word(m,m->R_AL);
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xd5*/
static void i86op_aad(PC_ENV *m)
{
m->R_AX = aad_word(m,m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xd6 ILLEGAL OPCODE */
/* opcode=0xd7 */
static void i86op_xlat(PC_ENV *m)
{
uint16 addr;
addr = m->R_BX + (uint8)m->R_AL;
m->R_AL = fetch_data_byte(m,addr);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe0*/
static void i86op_loopne(PC_ENV *m)
{
int16 ip;
ip = (int8)fetch_byte_imm(m);
ip += (int16)m->R_IP;
m->R_CX -= 1;
if (m->R_CX != 0 && !ACCESS_FLAG(m,F_ZF)) /* CX != 0 and !ZF */
m->R_IP = ip;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe1*/
static void i86op_loope(PC_ENV *m)
{
int16 ip;
ip = (int8)fetch_byte_imm(m);
ip += (int16)m->R_IP;
m->R_CX -= 1;
if (m->R_CX != 0 && ACCESS_FLAG(m,F_ZF)) /* CX != 0 and ZF */
m->R_IP = ip;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe2*/
static void i86op_loop(PC_ENV *m)
{
int16 ip;
ip = (int8)fetch_byte_imm(m);
ip += (int16)m->R_IP;
m->R_CX -= 1;
if (m->R_CX != 0)
m->R_IP = ip;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe3*/
static void i86op_jcxz(PC_ENV *m)
{
int16 offset,target;
/* jump to byte offset if overflow flag is set */
offset = (int8)fetch_byte_imm(m); /* sign extended ??? */
target = (int16)m->R_IP + offset;
if (m->R_CX == 0)
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe4*/
static void i86op_in_byte_AL_IMM(PC_ENV *m)
{
uint8 port;
port = (uint8)fetch_byte_imm(m);
m->R_AL = in(port);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe5*/
static void i86op_in_word_AX_IMM(PC_ENV *m)
{
uint8 port;
port = (uint8)fetch_byte_imm(m);
m->R_AX = in(port);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe6*/
static void i86op_out_byte_IMM_AL(PC_ENV *m)
{
uint8 port;
port = (uint8)fetch_byte_imm(m);
out(port, m->R_AL);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe7*/
static void i86op_out_word_IMM_AX(PC_ENV *m)
{
uint8 port;
port = (uint8)fetch_byte_imm(m);
out(port, m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe8*/
static void i86op_call_near_IMM(PC_ENV *m)
{
int16 ip;
/* weird. Thought this was a signed disp! */
ip = (int16)fetch_word_imm(m);
ip += (int16)m->R_IP; /* CHECK SIGN */
push_word(m,m->R_IP);
m->R_IP = ip;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xe9*/
static void i86op_jump_near_IMM(PC_ENV *m)
{
int ip;
/* weird. Thought this was a signed disp too! */
ip = (int16)fetch_word_imm(m);
ip += (int16)m->R_IP; /* CHECK SIGN */
m->R_IP = ip;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xea*/
static void i86op_jump_far_IMM(PC_ENV *m)
{
uint16 cs,ip;
ip = fetch_word_imm(m);
cs = fetch_word_imm(m);
m->R_IP = ip;
m->R_CS = cs;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xeb*/
static void i86op_jump_byte_IMM(PC_ENV *m)
{
int8 offset;
uint16 target;
offset = (int8) fetch_byte_imm(m); /* CHECK */
/* printf("jump byte imm offset=%d\n",offset);*/
target = (int16) m->R_IP + offset;
m->R_IP = target;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xec*/
static void i86op_in_byte_AL_DX(PC_ENV *m)
{
m->R_AL = in(m->R_DX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xed*/
static void i86op_in_word_AX_DX(PC_ENV *m)
{
m->R_AX = in(m->R_DX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xee*/
static void i86op_out_byte_DX_AL(PC_ENV *m)
{
out(m->R_DX, m->R_AL);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xef*/
static void i86op_out_word_DX_AX(PC_ENV *m)
{
out(m->R_DX, m->R_AX);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf0*/
static void i86op_lock(PC_ENV *m)
{
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf1 ILLEGAL OPERATION*/
/*opcode=0xf2*/
static void i86op_repne(PC_ENV *m)
{
m->sysmode |= SYSMODE_PREFIX_REPNE;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf3*/
static void i86op_repe(PC_ENV *m)
{
m->sysmode |= SYSMODE_PREFIX_REPE;
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf4*/
static void i86op_halt(PC_ENV *m)
{
halt_sys(m);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf5*/
static void i86op_cmc(PC_ENV *m)
{
/* complement the carry flag. */
TOGGLE_FLAG(m,F_CF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf6*/
static void i86op_opcF6_byte_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint8 *destreg;
uint16 destoffset;
uint8 destval,srcval;
/* long, drawn out code follows. Double switch for a total
of 32 cases. */
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0: /* mod=00 */
switch(rh)
{
case 0: /* test byte imm */
destoffset=decode_rm00_address(m,rl);
srcval = fetch_byte_imm(m);
destval = fetch_data_byte(m,destoffset);
test_byte(m, destval, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = not_byte(m, destval);
store_data_byte(m,destoffset,destval);
break;
case 3:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = neg_byte(m, destval);
store_data_byte(m,destoffset,destval);
break;
case 4:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
mul_byte(m, destval);
break;
case 5:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imul_byte(m, destval);
break;
case 6:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
div_byte(m, destval);
break;
case 7:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_byte(m,destoffset);
idiv_byte(m, destval);
break;
}
break; /* end mod==00 */
case 1: /* mod=01 */
switch(rh)
{
case 0: /* test byte imm */
destoffset=decode_rm01_address(m,rl);
srcval = fetch_byte_imm(m);
destval = fetch_data_byte(m,destoffset);
test_byte(m, destval, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = not_byte(m, destval);
store_data_byte(m,destoffset,destval);
break;
case 3:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = neg_byte(m, destval);
store_data_byte(m,destoffset,destval);
break;
case 4:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
mul_byte(m, destval);
break;
case 5:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imul_byte(m, destval);
break;
case 6:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
div_byte(m, destval);
break;
case 7:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_byte(m,destoffset);
idiv_byte(m, destval);
break;
}
break; /* end mod==01 */
case 2: /* mod=10 */
switch(rh)
{
case 0: /* test byte imm */
destoffset=decode_rm10_address(m,rl);
srcval = fetch_byte_imm(m);
destval = fetch_data_byte(m,destoffset);
test_byte(m, destval, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = not_byte(m, destval);
store_data_byte(m,destoffset,destval);
break;
case 3:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
destval = neg_byte(m, destval);
store_data_byte(m,destoffset,destval);
break;
case 4:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
mul_byte(m, destval);
break;
case 5:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
imul_byte(m, destval);
break;
case 6:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
div_byte(m, destval);
break;
case 7:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_byte(m,destoffset);
idiv_byte(m, destval);
break;
}
break; /* end mod==10 */
case 3: /* mod=11 */
switch(rh)
{
case 0: /* test byte imm */
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
srcval = fetch_byte_imm(m);
test_byte(m, *destreg, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = not_byte(m, *destreg);
break;
case 3:
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
*destreg = neg_byte(m, *destreg);
break;
case 4:
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
mul_byte(m, *destreg); /*!!! */
break;
case 5:
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
imul_byte(m, *destreg);
break;
case 6:
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
div_byte(m, *destreg);
break;
case 7:
destreg=DECODE_RM_BYTE_REGISTER(m,rl);
idiv_byte(m, *destreg);
break;
}
break; /* end mod==11 */
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf7*/
static void i86op_opcF7_word_RM(PC_ENV *m)
{
uint16 mod,rl,rh;
uint16 *destreg;
uint16 destoffset;
uint16 destval,srcval;
/* long, drawn out code follows. Double switch for a total
of 32 cases. */
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0: /* mod=00 */
switch(rh)
{
case 0: /* test word imm */
destoffset=decode_rm00_address(m,rl);
srcval = fetch_word_imm(m);
destval = fetch_data_word(m,destoffset);
test_word(m, destval, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = not_word(m, destval);
store_data_word(m,destoffset,destval);
break;
case 3:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = neg_word(m, destval);
store_data_word(m,destoffset,destval);
break;
case 4:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
mul_word(m, destval);
break;
case 5:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
imul_word(m, destval);
break;
case 6:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
div_word(m, destval);
break;
case 7:
destoffset=decode_rm00_address(m,rl);
destval = fetch_data_word(m,destoffset);
idiv_word(m, destval);
break;
}
break; /* end mod==00 */
case 1: /* mod=01 */
switch(rh)
{
case 0: /* test word imm */
destoffset=decode_rm01_address(m,rl);
srcval = fetch_word_imm(m);
destval = fetch_data_word(m,destoffset);
test_word(m, destval, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = not_word(m, destval);
store_data_word(m,destoffset,destval);
break;
case 3:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = neg_word(m, destval);
store_data_word(m,destoffset,destval);
break;
case 4:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
mul_word(m, destval);
break;
case 5:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
imul_word(m, destval);
break;
case 6:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
div_word(m, destval);
break;
case 7:
destoffset=decode_rm01_address(m,rl);
destval = fetch_data_word(m,destoffset);
idiv_word(m, destval);
break;
}
break; /* end mod==01 */
case 2: /* mod=10 */
switch(rh)
{
case 0: /* test word imm */
destoffset=decode_rm10_address(m,rl);
srcval = fetch_word_imm(m);
destval = fetch_data_word(m,destoffset);
test_word(m, destval, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = not_word(m, destval);
store_data_word(m,destoffset,destval);
break;
case 3:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
destval = neg_word(m, destval);
store_data_word(m,destoffset,destval);
break;
case 4:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
mul_word(m, destval);
break;
case 5:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
imul_word(m, destval);
break;
case 6:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
div_word(m, destval);
break;
case 7:
destoffset=decode_rm10_address(m,rl);
destval = fetch_data_word(m,destoffset);
idiv_word(m, destval);
break;
}
break; /* end mod==10 */
case 3: /* mod=11 */
switch(rh)
{
case 0: /* test word imm */
destreg=DECODE_RM_WORD_REGISTER(m,rl);
srcval = fetch_word_imm(m);
test_word(m, *destreg, srcval);
break;
case 1:
halt_sys(m);
break;
case 2:
destreg=DECODE_RM_WORD_REGISTER(m,rl);
*destreg = not_word(m, *destreg);
break;
case 3:
destreg=DECODE_RM_WORD_REGISTER(m,rl);
*destreg = neg_word(m, *destreg);
break;
case 4:
destreg=DECODE_RM_WORD_REGISTER(m,rl);
mul_word(m, *destreg); /*!!! */
break;
case 5:
destreg=DECODE_RM_WORD_REGISTER(m,rl);
imul_word(m, *destreg);
break;
case 6:
destreg=DECODE_RM_WORD_REGISTER(m,rl);
div_word(m, *destreg);
break;
case 7:
destreg=DECODE_RM_WORD_REGISTER(m,rl);
idiv_word(m, *destreg);
break;
}
break; /* end mod==11 */
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf8*/
static void i86op_clc(PC_ENV *m)
{
/* clear the carry flag. */
CLEAR_FLAG(m, F_CF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xf9*/
static void i86op_stc(PC_ENV *m)
{
/* set the carry flag. */
SET_FLAG(m, F_CF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xfa*/
static void i86op_cli(PC_ENV *m)
{
/* clear interrupts. */
CLEAR_FLAG(m, F_IF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xfb*/
static void i86op_sti(PC_ENV *m)
{
/* enable interrupts. */
SET_FLAG(m, F_IF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xfc*/
static void i86op_cld(PC_ENV *m)
{
/* clear interrupts. */
CLEAR_FLAG(m, F_DF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xfd*/
static void i86op_std(PC_ENV *m)
{
/* clear interrupts. */
SET_FLAG(m, F_DF);
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xfe*/
static void i86op_opcFE_byte_RM(PC_ENV *m)
{
/* Yet another damned special case instruction. */
uint16 mod,rh,rl;
uint8 destval;
uint16 destoffset;
uint8 *destreg;
/* ARRGH, ANOTHER GODDAMN SPECIAL CASE INSTRUCTION!!! */
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
switch (rh)
{
case 0: /* inc word ptr ... */
destval = fetch_data_byte(m,destoffset);
destval = inc_byte(m,destval);
store_data_byte(m,destoffset,destval);
break;
case 1: /* dec word ptr ... */
destval = fetch_data_byte(m,destoffset);
destval = dec_byte(m,destval);
store_data_byte(m,destoffset,destval);
break;
}
break;
case 1:
destoffset=decode_rm01_address(m,rl);
switch (rh)
{
case 0:
destval = fetch_data_byte(m,destoffset);
destval = inc_byte(m,destval);
store_data_byte(m,destoffset,destval);
break;
case 1:
destval = fetch_data_byte(m,destoffset);
destval = dec_byte(m,destval);
store_data_byte(m,destoffset,destval);
break;
}
break;
case 2:
destoffset=decode_rm10_address(m,rl);
switch (rh)
{
case 0:
destval = fetch_data_byte(m,destoffset);
destval = inc_byte(m,destval);
store_data_byte(m,destoffset,destval);
break;
case 1:
destval = fetch_data_byte(m,destoffset);
destval = dec_byte(m,destval);
store_data_byte(m,destoffset,destval);
break;
}
break;
case 3:
destreg = DECODE_RM_BYTE_REGISTER(m,rl);
switch (rh)
{
case 0:
*destreg = inc_byte(m,*destreg);
break;
case 1:
*destreg = dec_byte(m,*destreg);
break;
}
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/*opcode=0xff*/
static void i86op_opcFF_word_RM(PC_ENV *m)
{
uint16 mod,rh,rl;
uint16 destval,destval2;
uint16 destoffset;
uint16 *destreg;
/* ANOTHER DAMN SPECIAL CASE INSTRUCTION!!! */
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
destoffset=decode_rm00_address(m,rl);
switch (rh)
{
case 0: /* inc word ptr ... */
destval = fetch_data_word(m,destoffset);
destval = inc_word(m,destval);
store_data_word(m,destoffset,destval);
break;
case 1: /* dec word ptr ... */
destval = fetch_data_word(m,destoffset);
destval = dec_word(m,destval);
store_data_word(m,destoffset,destval);
break;
case 2: /* call word ptr ... */
destval = fetch_data_word(m,destoffset);
push_word(m,m->R_IP);
m->R_IP = destval;
break;
case 3: /* call far ptr ... */
destval = fetch_data_word(m,destoffset);
destval2 = fetch_data_word(m,destoffset+2);
push_word(m,m->R_CS);
m->R_CS = destval2;
push_word(m,m->R_IP);
m->R_IP = destval;
break;
case 4: /* jmp word ptr ... */
destval = fetch_data_word(m,destoffset);
m->R_IP = destval;
break;
case 5: /* jmp far ptr ... */
destval = fetch_data_word(m,destoffset);
destval2 = fetch_data_word(m,destoffset+2);
m->R_IP = destval;
m->R_CS = destval2;
break;
case 6: /* push word ptr ... */
destval = fetch_data_word(m,destoffset);
push_word(m,destval);
break;
}
break;
case 1:
destoffset=decode_rm01_address(m,rl);
switch (rh)
{
case 0:
destval = fetch_data_word(m,destoffset);
destval = inc_word(m,destval);
store_data_word(m,destoffset,destval);
break;
case 1:
destval = fetch_data_word(m,destoffset);
destval = dec_word(m,destval);
store_data_word(m,destoffset,destval);
break;
case 2: /* call word ptr ... */
destval = fetch_data_word(m,destoffset);
push_word(m,m->R_IP);
m->R_IP = destval;
break;
case 3: /* call far ptr ... */
destval = fetch_data_word(m,destoffset);
destval2 = fetch_data_word(m,destoffset+2);
push_word(m,m->R_CS);
m->R_CS = destval2;
push_word(m,m->R_IP);
m->R_IP = destval;
break;
case 4: /* jmp word ptr ... */
destval = fetch_data_word(m,destoffset);
m->R_IP = destval;
break;
case 5: /* jmp far ptr ... */
destval = fetch_data_word(m,destoffset);
destval2 = fetch_data_word(m,destoffset+2);
m->R_IP = destval;
m->R_CS = destval2;
break;
case 6: /* push word ptr ... */
destval = fetch_data_word(m,destoffset);
push_word(m,destval);
break;
}
break;
case 2:
destoffset=decode_rm10_address(m,rl);
switch (rh)
{
case 0:
destval = fetch_data_word(m,destoffset);
destval = inc_word(m,destval);
store_data_word(m,destoffset,destval);
break;
case 1:
destval = fetch_data_word(m,destoffset);
destval = dec_word(m,destval);
store_data_word(m,destoffset,destval);
break;
case 2: /* call word ptr ... */
destval = fetch_data_word(m,destoffset);
push_word(m,m->R_IP);
m->R_IP = destval;
break;
case 3: /* call far ptr ... */
destval = fetch_data_word(m,destoffset);
destval2 = fetch_data_word(m,destoffset+2);
push_word(m,m->R_CS);
m->R_CS = destval2;
push_word(m,m->R_IP);
m->R_IP = destval;
break;
case 4: /* jmp word ptr ... */
destval = fetch_data_word(m,destoffset);
m->R_IP = destval;
break;
case 5: /* jmp far ptr ... */
destval = fetch_data_word(m,destoffset);
destval2 = fetch_data_word(m,destoffset+2);
m->R_IP = destval;
m->R_CS = destval2;
break;
case 6: /* push word ptr ... */
destval = fetch_data_word(m,destoffset);
push_word(m,destval);
break;
}
break;
case 3:
destreg = DECODE_RM_WORD_REGISTER(m,rl);
switch (rh)
{
case 0:
*destreg = inc_word(m,*destreg);
break;
case 1:
*destreg = dec_word(m,*destreg);
break;
case 2: /* call word ptr ... */
push_word(m,m->R_IP);
m->R_IP = *destreg;
break;
case 3: /* jmp far ptr ... */
halt_sys(m);
break;
case 4: /* jmp ... */
m->R_IP = (uint16)(*destreg);
break;
case 5: /* jmp far ptr ... */
halt_sys(m);
break;
case 6:
push_word(m,*destreg);
break;
}
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xd8*/
static void i86op_esc_coprocess_d8(PC_ENV *m)
{
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xd9*/
static void i86op_esc_coprocess_d9(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xda*/
static void i86op_esc_coprocess_da(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xdb*/
static void i86op_esc_coprocess_db(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xdc*/
static void i86op_esc_coprocess_dc(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xdd*/
static void i86op_esc_coprocess_dd(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xde*/
static void i86op_esc_coprocess_de(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* opcode=0xdf*/
static void i86op_esc_coprocess_df(PC_ENV *m)
{
uint16 mod,rl,rh;
FETCH_DECODE_MODRM(m,mod,rh,rl);
switch (mod)
{
case 0:
decode_rm00_address(m,rl);
break;
case 1:
decode_rm01_address(m,rl);
break;
case 2:
decode_rm10_address(m,rl);
break;
case 3: /* register to register */
break;
}
DECODE_CLEAR_SEGOVR(m);
}
/* OPERAND TABLE */
OP i86_optab[256] = {
/* 0x00 */ i86op_add_byte_RM_R,
/* 0x01 */ i86op_add_word_RM_R,
/* 0x02 */ i86op_add_byte_R_RM,
/* 0x03 */ i86op_add_word_R_RM,
/* 0x04 */ i86op_add_byte_AL_IMM,
/* 0x05 */ i86op_add_word_AX_IMM,
/* 0x06 */ i86op_push_ES,
/* 0x07 */ i86op_pop_ES,
/* 0x08 */ i86op_or_byte_RM_R,
/* 0x09 */ i86op_or_word_RM_R,
/* 0x0a */ i86op_or_byte_R_RM,
/* 0x0b */ i86op_or_word_R_RM,
/* 0x0c */ i86op_or_byte_AL_IMM,
/* 0x0d */ i86op_or_word_AX_IMM,
/* 0x0e */ i86op_push_CS,
/* 0x0f */ i86op_illegal_op,
/* 0x10 */ i86op_adc_byte_RM_R,
/* 0x11 */ i86op_adc_word_RM_R,
/* 0x12 */ i86op_adc_byte_R_RM,
/* 0x13 */ i86op_adc_word_R_RM,
/* 0x14 */ i86op_adc_byte_AL_IMM,
/* 0x15 */ i86op_adc_word_AX_IMM,
/* 0x16 */ i86op_push_SS,
/* 0x17 */ i86op_pop_SS,
/* 0x18 */ i86op_sbb_byte_RM_R,
/* 0x19 */ i86op_sbb_word_RM_R,
/* 0x1a */ i86op_sbb_byte_R_RM,
/* 0x1b */ i86op_sbb_word_R_RM,
/* 0x1c */ i86op_sbb_byte_AL_IMM,
/* 0x1d */ i86op_sbb_word_AX_IMM,
/* 0x1e */ i86op_push_DS,
/* 0x1f */ i86op_pop_DS,
/* 0x20 */ i86op_and_byte_RM_R,
/* 0x21 */ i86op_and_word_RM_R,
/* 0x22 */ i86op_and_byte_R_RM,
/* 0x23 */ i86op_and_word_R_RM,
/* 0x24 */ i86op_and_byte_AL_IMM,
/* 0x25 */ i86op_and_word_AX_IMM,
/* 0x26 */ i86op_segovr_ES,
/* 0x27 */ i86op_daa,
/* 0x28 */ i86op_sub_byte_RM_R,
/* 0x29 */ i86op_sub_word_RM_R,
/* 0x2a */ i86op_sub_byte_R_RM,
/* 0x2b */ i86op_sub_word_R_RM,
/* 0x2c */ i86op_sub_byte_AL_IMM,
/* 0x2d */ i86op_sub_word_AX_IMM,
/* 0x2e */ i86op_segovr_CS,
/* 0x2f */ i86op_das,
/* 0x30 */ i86op_xor_byte_RM_R,
/* 0x31 */ i86op_xor_word_RM_R,
/* 0x32 */ i86op_xor_byte_R_RM,
/* 0x33 */ i86op_xor_word_R_RM,
/* 0x34 */ i86op_xor_byte_AL_IMM,
/* 0x35 */ i86op_xor_word_AX_IMM,
/* 0x36 */ i86op_segovr_SS,
/* 0x37 */ i86op_aaa,
/* 0x38 */ i86op_cmp_byte_RM_R,
/* 0x39 */ i86op_cmp_word_RM_R,
/* 0x3a */ i86op_cmp_byte_R_RM,
/* 0x3b */ i86op_cmp_word_R_RM,
/* 0x3c */ i86op_cmp_byte_AL_IMM,
/* 0x3d */ i86op_cmp_word_AX_IMM,
/* 0x3e */ i86op_segovr_DS,
/* 0x3f */ i86op_aas,
/* 0x40 */ i86op_inc_AX,
/* 0x41 */ i86op_inc_CX,
/* 0x42 */ i86op_inc_DX,
/* 0x43 */ i86op_inc_BX,
/* 0x44 */ i86op_inc_SP,
/* 0x45 */ i86op_inc_BP,
/* 0x46 */ i86op_inc_SI,
/* 0x47 */ i86op_inc_DI,
/* 0x48 */ i86op_dec_AX,
/* 0x49 */ i86op_dec_CX,
/* 0x4a */ i86op_dec_DX,
/* 0x4b */ i86op_dec_BX,
/* 0x4c */ i86op_dec_SP,
/* 0x4d */ i86op_dec_BP,
/* 0x4e */ i86op_dec_SI,
/* 0x4f */ i86op_dec_DI,
/* 0x50 */ i86op_push_AX,
/* 0x51 */ i86op_push_CX,
/* 0x52 */ i86op_push_DX,
/* 0x53 */ i86op_push_BX,
/* 0x54 */ i86op_push_SP,
/* 0x55 */ i86op_push_BP,
/* 0x56 */ i86op_push_SI,
/* 0x57 */ i86op_push_DI,
/* 0x58 */ i86op_pop_AX,
/* 0x59 */ i86op_pop_CX,
/* 0x5a */ i86op_pop_DX,
/* 0x5b */ i86op_pop_BX,
/* 0x5c */ i86op_pop_SP,
/* 0x5d */ i86op_pop_BP,
/* 0x5e */ i86op_pop_SI,
/* 0x5f */ i86op_pop_DI,
/* 0x60 */ i86op_illegal_op,
/* 0x61 */ i86op_illegal_op,
/* 0x62 */ i86op_illegal_op,
/* 0x63 */ i86op_illegal_op,
/* 0x64 */ i86op_illegal_op,
/* 0x65 */ i86op_illegal_op,
/* 0x66 */ i86op_illegal_op,
/* 0x67 */ i86op_illegal_op,
/* 0x68 */ i86op_illegal_op,
/* 0x69 */ i86op_illegal_op,
/* 0x6a */ i86op_illegal_op,
/* 0x6b */ i86op_illegal_op,
/* 0x6c */ i86op_illegal_op,
/* 0x6d */ i86op_illegal_op,
/* 0x6e */ i86op_illegal_op,
/* 0x6f */ i86op_illegal_op,
/* 0x70 */ i86op_jump_near_O,
/* 0x71 */ i86op_jump_near_NO,
/* 0x72 */ i86op_jump_near_B,
/* 0x73 */ i86op_jump_near_NB,
/* 0x74 */ i86op_jump_near_Z,
/* 0x75 */ i86op_jump_near_NZ,
/* 0x76 */ i86op_jump_near_BE,
/* 0x77 */ i86op_jump_near_NBE,
/* 0x78 */ i86op_jump_near_S,
/* 0x79 */ i86op_jump_near_NS,
/* 0x7a */ i86op_jump_near_P,
/* 0x7b */ i86op_jump_near_NP,
/* 0x7c */ i86op_jump_near_L,
/* 0x7d */ i86op_jump_near_NL,
/* 0x7e */ i86op_jump_near_LE,
/* 0x7f */ i86op_jump_near_NLE,
/* 0x80 */ i86op_opc80_byte_RM_IMM,
/* 0x81 */ i86op_opc81_word_RM_IMM,
/* 0x82 */ i86op_opc82_byte_RM_IMM,
/* 0x83 */ i86op_opc83_word_RM_IMM,
/* 0x84 */ i86op_test_byte_RM_R,
/* 0x85 */ i86op_test_word_RM_R,
/* 0x86 */ i86op_xchg_byte_RM_R,
/* 0x87 */ i86op_xchg_word_RM_R,
/* 0x88 */ i86op_mov_byte_RM_R,
/* 0x89 */ i86op_mov_word_RM_R,
/* 0x8a */ i86op_mov_byte_R_RM,
/* 0x8b */ i86op_mov_word_R_RM,
/* 0x8c */ i86op_mov_word_RM_SR,
/* 0x8d */ i86op_lea_word_R_M,
/* 0x8e */ i86op_mov_word_SR_RM,
/* 0x8f */ i86op_pop_RM,
/* 0x90 */ i86op_nop,
/* 0x91 */ i86op_xchg_word_AX_CX,
/* 0x92 */ i86op_xchg_word_AX_DX,
/* 0x93 */ i86op_xchg_word_AX_BX,
/* 0x94 */ i86op_xchg_word_AX_SP,
/* 0x95 */ i86op_xchg_word_AX_BP ,
/* 0x96 */ i86op_xchg_word_AX_SI ,
/* 0x97 */ i86op_xchg_word_AX_DI ,
/* 0x98 */ i86op_cbw,
/* 0x99 */ i86op_cwd,
/* 0x9a */ i86op_call_far_IMM,
/* 0x9b */ i86op_wait,
/* 0x9c */ i86op_pushf_word,
/* 0x9d */ i86op_popf_word,
/* 0x9e */ i86op_sahf,
/* 0x9f */ i86op_lahf,
/* 0xa0 */ i86op_mov_AL_M_IMM,
/* 0xa1 */ i86op_mov_AX_M_IMM,
/* 0xa2 */ i86op_mov_M_AL_IMM,
/* 0xa3 */ i86op_mov_M_AX_IMM,
/* 0xa4 */ i86op_movs_byte,
/* 0xa5 */ i86op_movs_word,
/* 0xa6 */ i86op_cmps_byte,
/* 0xa7 */ i86op_cmps_word,
/* 0xa8 */ i86op_test_AL_IMM,
/* 0xa9 */ i86op_test_AX_IMM,
/* 0xaa */ i86op_stos_byte,
/* 0xab */ i86op_stos_word,
/* 0xac */ i86op_lods_byte,
/* 0xad */ i86op_lods_word,
/* 0xac */ i86op_scas_byte,
/* 0xad */ i86op_scas_word,
/* 0xb0 */ i86op_mov_byte_AL_IMM,
/* 0xb1 */ i86op_mov_byte_CL_IMM,
/* 0xb2 */ i86op_mov_byte_DL_IMM,
/* 0xb3 */ i86op_mov_byte_BL_IMM,
/* 0xb4 */ i86op_mov_byte_AH_IMM,
/* 0xb5 */ i86op_mov_byte_CH_IMM,
/* 0xb6 */ i86op_mov_byte_DH_IMM,
/* 0xb7 */ i86op_mov_byte_BH_IMM,
/* 0xb8 */ i86op_mov_word_AX_IMM,
/* 0xb9 */ i86op_mov_word_CX_IMM,
/* 0xba */ i86op_mov_word_DX_IMM,
/* 0xbb */ i86op_mov_word_BX_IMM,
/* 0xbc */ i86op_mov_word_SP_IMM,
/* 0xbd */ i86op_mov_word_BP_IMM,
/* 0xbe */ i86op_mov_word_SI_IMM,
/* 0xbf */ i86op_mov_word_DI_IMM,
/* 0xc0 */ i86op_illegal_op,
/* 0xc1 */ i86op_illegal_op,
/* 0xc2 */ i86op_ret_near_IMM,
/* 0xc3 */ i86op_ret_near,
/* 0xc4 */ i86op_les_R_IMM,
/* 0xc5 */ i86op_lds_R_IMM,
/* 0xc6 */ i86op_mov_byte_RM_IMM,
/* 0xc7 */ i86op_mov_word_RM_IMM,
/* 0xc8 */ i86op_illegal_op,
/* 0xc9 */ i86op_illegal_op,
/* 0xca */ i86op_ret_far_IMM,
/* 0xcb */ i86op_ret_far,
/* 0xcc */ i86op_int3,
/* 0xcd */ i86op_int_IMM,
/* 0xce */ i86op_into,
/* 0xcf */ i86op_iret,
/* 0xd0 */ i86op_opcD0_byte_RM_1,
/* 0xd1 */ i86op_opcD1_word_RM_1,
/* 0xd2 */ i86op_opcD2_byte_RM_CL,
/* 0xd3 */ i86op_opcD3_word_RM_CL,
/* 0xd4 */ i86op_aam,
/* 0xd5 */ i86op_aad,
/* 0xd6 */ i86op_illegal_op,
/* 0xd7 */ i86op_xlat,
/* 0xd8 */ i86op_esc_coprocess_d8,
/* 0xd9 */ i86op_esc_coprocess_d9,
/* 0xda */ i86op_esc_coprocess_da,
/* 0xdb */ i86op_esc_coprocess_db,
/* 0xdc */ i86op_esc_coprocess_dc,
/* 0xdd */ i86op_esc_coprocess_dd,
/* 0xde */ i86op_esc_coprocess_de,
/* 0xdf */ i86op_esc_coprocess_df,
/* 0xe0 */ i86op_loopne,
/* 0xe1 */ i86op_loope,
/* 0xe2 */ i86op_loop,
/* 0xe3 */ i86op_jcxz,
/* 0xe4 */ i86op_in_byte_AL_IMM,
/* 0xe5 */ i86op_in_word_AX_IMM,
/* 0xe6 */ i86op_out_byte_IMM_AL,
/* 0xe7 */ i86op_out_word_IMM_AX,
/* 0xe8 */ i86op_call_near_IMM,
/* 0xe9 */ i86op_jump_near_IMM,
/* 0xea */ i86op_jump_far_IMM,
/* 0xeb */ i86op_jump_byte_IMM,
/* 0xec */ i86op_in_byte_AL_DX,
/* 0xed */ i86op_in_word_AX_DX,
/* 0xee */ i86op_out_byte_DX_AL,
/* 0xef */ i86op_out_word_DX_AX,
/* 0xf0 */ i86op_lock,
/* 0xf1 */ i86op_illegal_op,
/* 0xf2 */ i86op_repne,
/* 0xf3 */ i86op_repe,
/* 0xf4 */ i86op_halt,
/* 0xf5 */ i86op_cmc,
/* 0xf6 */ i86op_opcF6_byte_RM,
/* 0xf7 */ i86op_opcF7_word_RM,
/* 0xf8 */ i86op_clc,
/* 0xf9 */ i86op_stc,
/* 0xfa */ i86op_cli,
/* 0xfb */ i86op_sti,
/* 0xfc */ i86op_cld,
/* 0xfd */ i86op_std,
/* 0xfe */ i86op_opcFE_byte_RM,
/* 0xff */ i86op_opcFF_word_RM,
};