The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/x86emu/x86emu.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: x86emu.c,v 1.9 2014/06/15 11:04:49 pirofti Exp $      */
    2 /*      $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */
    3 
    4 /*
    5  *
    6  *  Realmode X86 Emulator Library
    7  *
    8  *  Copyright (C) 1996-1999 SciTech Software, Inc.
    9  *  Copyright (C) David Mosberger-Tang
   10  *  Copyright (C) 1999 Egbert Eich
   11  *  Copyright (C) 2007 Joerg Sonnenberger
   12  *
   13  *  ========================================================================
   14  *
   15  *  Permission to use, copy, modify, distribute, and sell this software and
   16  *  its documentation for any purpose is hereby granted without fee,
   17  *  provided that the above copyright notice appear in all copies and that
   18  *  both that copyright notice and this permission notice appear in
   19  *  supporting documentation, and that the name of the authors not be used
   20  *  in advertising or publicity pertaining to distribution of the software
   21  *  without specific, written prior permission.  The authors makes no
   22  *  representations about the suitability of this software for any purpose.
   23  *  It is provided "as is" without express or implied warranty.
   24  *
   25  *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   26  *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
   27  *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
   28  *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
   29  *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   30  *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   31  *  PERFORMANCE OF THIS SOFTWARE.
   32  *
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #include <contrib/x86emu/x86emu.h>
   39 #include <contrib/x86emu/x86emu_regs.h>
   40 
   41 static void     x86emu_intr_raise (struct x86emu *, uint8_t type);
   42 
   43 static void     x86emu_exec_one_byte(struct x86emu *);
   44 static void     x86emu_exec_two_byte(struct x86emu *);
   45 
   46 static void     fetch_decode_modrm (struct x86emu *);
   47 static uint8_t  fetch_byte_imm (struct x86emu *);
   48 static uint16_t fetch_word_imm (struct x86emu *);
   49 static uint32_t fetch_long_imm (struct x86emu *);
   50 static uint8_t  fetch_data_byte (struct x86emu *, uint32_t offset);
   51 static uint8_t  fetch_byte (struct x86emu *, u_int segment, uint32_t offset);
   52 static uint16_t fetch_data_word (struct x86emu *, uint32_t offset);
   53 static uint16_t fetch_word (struct x86emu *, uint32_t segment, uint32_t offset);
   54 static uint32_t fetch_data_long (struct x86emu *, uint32_t offset);
   55 static uint32_t fetch_long (struct x86emu *, uint32_t segment, uint32_t offset);
   56 static void     store_data_byte (struct x86emu *, uint32_t offset, uint8_t val);
   57 static void     store_byte (struct x86emu *, uint32_t segment, uint32_t offset, uint8_t val);
   58 static void     store_data_word (struct x86emu *, uint32_t offset, uint16_t val);
   59 static void     store_word (struct x86emu *, uint32_t segment, uint32_t offset, uint16_t val);
   60 static void     store_data_long (struct x86emu *, uint32_t offset, uint32_t val);
   61 static void     store_long (struct x86emu *, uint32_t segment, uint32_t offset, uint32_t val);
   62 static uint8_t* decode_rl_byte_register(struct x86emu *);
   63 static uint16_t*        decode_rl_word_register(struct x86emu *);
   64 static uint32_t*        decode_rl_long_register(struct x86emu *);
   65 static uint8_t*         decode_rh_byte_register(struct x86emu *);
   66 static uint16_t*        decode_rh_word_register(struct x86emu *);
   67 static uint32_t*        decode_rh_long_register(struct x86emu *);
   68 static uint16_t*        decode_rh_seg_register(struct x86emu *);
   69 static uint32_t decode_rl_address(struct x86emu *);
   70 
   71 static uint8_t  decode_and_fetch_byte(struct x86emu *);
   72 static uint16_t         decode_and_fetch_word(struct x86emu *);
   73 static uint32_t         decode_and_fetch_long(struct x86emu *);
   74 
   75 static uint8_t  decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *);
   76 static uint16_t         decode_and_fetch_word_imm8(struct x86emu *, uint8_t *);
   77 static uint32_t         decode_and_fetch_long_imm8(struct x86emu *, uint8_t *);
   78 
   79 static uint16_t         decode_and_fetch_word_disp(struct x86emu *, int16_t);
   80 static uint32_t         decode_and_fetch_long_disp(struct x86emu *, int16_t);
   81 
   82 static void     write_back_byte(struct x86emu *, uint8_t);
   83 static void     write_back_word(struct x86emu *, uint16_t);
   84 static void     write_back_long(struct x86emu *, uint32_t);
   85 
   86 static uint16_t aaa_word (struct x86emu *, uint16_t d);
   87 static uint16_t aas_word (struct x86emu *, uint16_t d);
   88 static uint16_t aad_word (struct x86emu *, uint16_t d);
   89 static uint16_t aam_word (struct x86emu *, uint8_t d);
   90 static uint8_t  adc_byte (struct x86emu *, uint8_t d, uint8_t s);
   91 static uint16_t adc_word (struct x86emu *, uint16_t d, uint16_t s);
   92 static uint32_t adc_long (struct x86emu *, uint32_t d, uint32_t s);
   93 static uint8_t  add_byte (struct x86emu *, uint8_t d, uint8_t s);
   94 static uint16_t add_word (struct x86emu *, uint16_t d, uint16_t s);
   95 static uint32_t add_long (struct x86emu *, uint32_t d, uint32_t s);
   96 static uint8_t  and_byte (struct x86emu *, uint8_t d, uint8_t s);
   97 static uint16_t and_word (struct x86emu *, uint16_t d, uint16_t s);
   98 static uint32_t and_long (struct x86emu *, uint32_t d, uint32_t s);
   99 static uint8_t  cmp_byte (struct x86emu *, uint8_t d, uint8_t s);
  100 static uint16_t cmp_word (struct x86emu *, uint16_t d, uint16_t s);
  101 static uint32_t cmp_long (struct x86emu *, uint32_t d, uint32_t s);
  102 static void     cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s);
  103 static void     cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s);
  104 static void     cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s);
  105 static uint8_t  daa_byte (struct x86emu *, uint8_t d);
  106 static uint8_t  das_byte (struct x86emu *, uint8_t d);
  107 static uint8_t  dec_byte (struct x86emu *, uint8_t d);
  108 static uint16_t dec_word (struct x86emu *, uint16_t d);
  109 static uint32_t dec_long (struct x86emu *, uint32_t d);
  110 static uint8_t  inc_byte (struct x86emu *, uint8_t d);
  111 static uint16_t inc_word (struct x86emu *, uint16_t d);
  112 static uint32_t inc_long (struct x86emu *, uint32_t d);
  113 static uint8_t  or_byte (struct x86emu *, uint8_t d, uint8_t s);
  114 static uint16_t or_word (struct x86emu *, uint16_t d, uint16_t s);
  115 static uint32_t or_long (struct x86emu *, uint32_t d, uint32_t s);
  116 static uint8_t  neg_byte (struct x86emu *, uint8_t s);
  117 static uint16_t neg_word (struct x86emu *, uint16_t s);
  118 static uint32_t neg_long (struct x86emu *, uint32_t s);
  119 static uint8_t  rcl_byte (struct x86emu *, uint8_t d, uint8_t s);
  120 static uint16_t rcl_word (struct x86emu *, uint16_t d, uint8_t s);
  121 static uint32_t rcl_long (struct x86emu *, uint32_t d, uint8_t s);
  122 static uint8_t  rcr_byte (struct x86emu *, uint8_t d, uint8_t s);
  123 static uint16_t rcr_word (struct x86emu *, uint16_t d, uint8_t s);
  124 static uint32_t rcr_long (struct x86emu *, uint32_t d, uint8_t s);
  125 static uint8_t  rol_byte (struct x86emu *, uint8_t d, uint8_t s);
  126 static uint16_t rol_word (struct x86emu *, uint16_t d, uint8_t s);
  127 static uint32_t rol_long (struct x86emu *, uint32_t d, uint8_t s);
  128 static uint8_t  ror_byte (struct x86emu *, uint8_t d, uint8_t s);
  129 static uint16_t ror_word (struct x86emu *, uint16_t d, uint8_t s);
  130 static uint32_t ror_long (struct x86emu *, uint32_t d, uint8_t s);
  131 static uint8_t  shl_byte (struct x86emu *, uint8_t d, uint8_t s);
  132 static uint16_t shl_word (struct x86emu *, uint16_t d, uint8_t s);
  133 static uint32_t shl_long (struct x86emu *, uint32_t d, uint8_t s);
  134 static uint8_t  shr_byte (struct x86emu *, uint8_t d, uint8_t s);
  135 static uint16_t shr_word (struct x86emu *, uint16_t d, uint8_t s);
  136 static uint32_t shr_long (struct x86emu *, uint32_t d, uint8_t s);
  137 static uint8_t  sar_byte (struct x86emu *, uint8_t d, uint8_t s);
  138 static uint16_t sar_word (struct x86emu *, uint16_t d, uint8_t s);
  139 static uint32_t sar_long (struct x86emu *, uint32_t d, uint8_t s);
  140 static uint16_t shld_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s);
  141 static uint32_t shld_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s);
  142 static uint16_t shrd_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s);
  143 static uint32_t shrd_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s);
  144 static uint8_t  sbb_byte (struct x86emu *, uint8_t d, uint8_t s);
  145 static uint16_t sbb_word (struct x86emu *, uint16_t d, uint16_t s);
  146 static uint32_t sbb_long (struct x86emu *, uint32_t d, uint32_t s);
  147 static uint8_t  sub_byte (struct x86emu *, uint8_t d, uint8_t s);
  148 static uint16_t sub_word (struct x86emu *, uint16_t d, uint16_t s);
  149 static uint32_t sub_long (struct x86emu *, uint32_t d, uint32_t s);
  150 static void     test_byte (struct x86emu *, uint8_t d, uint8_t s);
  151 static void     test_word (struct x86emu *, uint16_t d, uint16_t s);
  152 static void     test_long (struct x86emu *, uint32_t d, uint32_t s);
  153 static uint8_t  xor_byte (struct x86emu *, uint8_t d, uint8_t s);
  154 static uint16_t xor_word (struct x86emu *, uint16_t d, uint16_t s);
  155 static uint32_t xor_long (struct x86emu *, uint32_t d, uint32_t s);
  156 static void     imul_byte (struct x86emu *, uint8_t s);
  157 static void     imul_word (struct x86emu *, uint16_t s);
  158 static void     imul_long (struct x86emu *, uint32_t s);
  159 static void     mul_byte (struct x86emu *, uint8_t s);
  160 static void     mul_word (struct x86emu *, uint16_t s);
  161 static void     mul_long (struct x86emu *, uint32_t s);
  162 static void     idiv_byte (struct x86emu *, uint8_t s);
  163 static void     idiv_word (struct x86emu *, uint16_t s);
  164 static void     idiv_long (struct x86emu *, uint32_t s);
  165 static void     div_byte (struct x86emu *, uint8_t s);
  166 static void     div_word (struct x86emu *, uint16_t s);
  167 static void     div_long (struct x86emu *, uint32_t s);
  168 static void     ins (struct x86emu *, int size);
  169 static void     outs (struct x86emu *, int size);
  170 static void     push_word (struct x86emu *, uint16_t w);
  171 static void     push_long (struct x86emu *, uint32_t w);
  172 static uint16_t pop_word (struct x86emu *);
  173 static uint32_t pop_long (struct x86emu *);
  174 
  175 /*
  176  * REMARKS:
  177  * Handles any pending asychronous interrupts.
  178  */
  179 static void
  180 x86emu_intr_dispatch(struct x86emu *emu, uint8_t intno)
  181 {
  182         if (emu->_x86emu_intrTab[intno]) {
  183                 (*emu->_x86emu_intrTab[intno]) (emu, intno);
  184         } else {
  185                 push_word(emu, (uint16_t) emu->x86.R_FLG);
  186                 CLEAR_FLAG(F_IF);
  187                 CLEAR_FLAG(F_TF);
  188                 push_word(emu, emu->x86.R_CS);
  189                 emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2);
  190                 push_word(emu, emu->x86.R_IP);
  191                 emu->x86.R_IP = fetch_word(emu, 0, intno * 4);
  192         }
  193 }
  194 
  195 static void 
  196 x86emu_intr_handle(struct x86emu *emu)
  197 {
  198         uint8_t intno;
  199 
  200         if (emu->x86.intr & INTR_SYNCH) {
  201                 intno = emu->x86.intno;
  202                 emu->x86.intr = 0;
  203                 x86emu_intr_dispatch(emu, intno);
  204         }
  205 }
  206 
  207 /*
  208  * PARAMETERS:
  209  * intrnum - Interrupt number to raise
  210  * 
  211  * REMARKS:
  212  * Raise the specified interrupt to be handled before the execution of the
  213  * next instruction.
  214  */
  215 void 
  216 x86emu_intr_raise(struct x86emu *emu, uint8_t intrnum)
  217 {
  218         emu->x86.intno = intrnum;
  219         emu->x86.intr |= INTR_SYNCH;
  220 }
  221 
  222 /*
  223  * REMARKS:
  224  * Main execution loop for the emulator. We return from here when the system
  225  * halts, which is normally caused by a stack fault when we return from the
  226  * original real mode call.
  227  */
  228 void 
  229 x86emu_exec(struct x86emu *emu)
  230 {
  231         emu->x86.intr = 0;
  232 
  233         if (setjmp(emu->exec_state))
  234                 return;
  235 
  236         for (;;) {
  237                 if (emu->x86.intr) {
  238                         if (((emu->x86.intr & INTR_SYNCH) &&
  239                             (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
  240                             !ACCESS_FLAG(F_IF)) {
  241                                 x86emu_intr_handle(emu);
  242                         }
  243                 }
  244                 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
  245                         return;
  246                 x86emu_exec_one_byte(emu);
  247                 ++emu->cur_cycles;
  248         }
  249 }
  250 
  251 void
  252 x86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off)
  253 {
  254         push_word(emu, 0);
  255         push_word(emu, 0);
  256         emu->x86.R_CS = seg;
  257         emu->x86.R_IP = off;
  258 
  259         x86emu_exec(emu);
  260 }
  261 
  262 void
  263 x86emu_exec_intr(struct x86emu *emu, uint8_t intr)
  264 {
  265         push_word(emu, emu->x86.R_FLG);
  266         CLEAR_FLAG(F_IF);
  267         CLEAR_FLAG(F_TF);
  268         push_word(emu, 0);
  269         push_word(emu, 0);
  270         emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
  271         emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
  272         emu->x86.intr = 0;
  273 
  274         x86emu_exec(emu);
  275 }
  276 
  277 /*
  278  * REMARKS:
  279  * Halts the system by setting the halted system flag.
  280  */
  281 void 
  282 x86emu_halt_sys(struct x86emu *emu)
  283 {
  284         longjmp(emu->exec_state, 1);
  285 }
  286 
  287 /*
  288  * PARAMETERS:
  289  * mod          - Mod value from decoded byte
  290  * regh - Reg h value from decoded byte
  291  * regl - Reg l value from decoded byte
  292  * 
  293  * REMARKS:
  294  * Raise the specified interrupt to be handled before the execution of the
  295  * next instruction.
  296  * 
  297  * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
  298  */
  299 static void 
  300 fetch_decode_modrm(struct x86emu *emu)
  301 {
  302         int fetched;
  303 
  304         fetched = fetch_byte_imm(emu);
  305         emu->cur_mod = (fetched >> 6) & 0x03;
  306         emu->cur_rh = (fetched >> 3) & 0x07;
  307         emu->cur_rl = (fetched >> 0) & 0x07;
  308 }
  309 
  310 /*
  311  * RETURNS:
  312  * Immediate byte value read from instruction queue
  313  * 
  314  * REMARKS:
  315  * This function returns the immediate byte from the instruction queue, and
  316  * moves the instruction pointer to the next value.
  317  * 
  318  * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
  319  */
  320 static uint8_t 
  321 fetch_byte_imm(struct x86emu *emu)
  322 {
  323         uint8_t fetched;
  324 
  325         fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
  326         emu->x86.R_IP++;
  327         return fetched;
  328 }
  329 
  330 /*
  331  * RETURNS:
  332  * Immediate word value read from instruction queue
  333  * 
  334  * REMARKS:
  335  * This function returns the immediate byte from the instruction queue, and
  336  * moves the instruction pointer to the next value.
  337  * 
  338  * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
  339  */
  340 static uint16_t 
  341 fetch_word_imm(struct x86emu *emu)
  342 {
  343         uint16_t fetched;
  344 
  345         fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
  346         emu->x86.R_IP += 2;
  347         return fetched;
  348 }
  349 
  350 /*
  351  * RETURNS:
  352  * Immediate lone value read from instruction queue
  353  * 
  354  * REMARKS:
  355  * This function returns the immediate byte from the instruction queue, and
  356  * moves the instruction pointer to the next value.
  357  * 
  358  * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
  359  */
  360 static uint32_t 
  361 fetch_long_imm(struct x86emu *emu)
  362 {
  363         uint32_t fetched;
  364 
  365         fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
  366         emu->x86.R_IP += 4;
  367         return fetched;
  368 }
  369 
  370 /*
  371  * RETURNS:
  372  * Value of the default data segment
  373  * 
  374  * REMARKS:
  375  * Inline function that returns the default data segment for the current
  376  * instruction.
  377  * 
  378  * On the x86 processor, the default segment is not always DS if there is
  379  * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
  380  * addresses relative to SS (ie: on the stack). So, at the minimum, all
  381  * decodings of addressing modes would have to set/clear a bit describing
  382  * whether the access is relative to DS or SS.  That is the function of the
  383  * cpu-state-varible emu->x86.mode. There are several potential states:
  384  * 
  385  *      repe prefix seen  (handled elsewhere)
  386  *      repne prefix seen  (ditto)
  387  * 
  388  *      cs segment override
  389  *      ds segment override
  390  *      es segment override
  391  *      fs segment override
  392  *      gs segment override
  393  *      ss segment override
  394  * 
  395  *      ds/ss select (in absense of override)
  396  * 
  397  * Each of the above 7 items are handled with a bit in the mode field.
  398  */
  399 static uint32_t 
  400 get_data_segment(struct x86emu *emu)
  401 {
  402         switch (emu->x86.mode & SYSMODE_SEGMASK) {
  403         case 0:         /* default case: use ds register */
  404         case SYSMODE_SEGOVR_DS:
  405         case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
  406                 return emu->x86.R_DS;
  407         case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */
  408                 return emu->x86.R_SS;
  409         case SYSMODE_SEGOVR_CS:
  410         case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
  411                 return emu->x86.R_CS;
  412         case SYSMODE_SEGOVR_ES:
  413         case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
  414                 return emu->x86.R_ES;
  415         case SYSMODE_SEGOVR_FS:
  416         case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
  417                 return emu->x86.R_FS;
  418         case SYSMODE_SEGOVR_GS:
  419         case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
  420                 return emu->x86.R_GS;
  421         case SYSMODE_SEGOVR_SS:
  422         case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
  423                 return emu->x86.R_SS;
  424         }
  425         x86emu_halt_sys(emu);
  426 }
  427 
  428 /*
  429  * PARAMETERS:
  430  * offset       - Offset to load data from
  431  * 
  432  * RETURNS:
  433  * Byte value read from the absolute memory location.
  434  * 
  435  * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
  436  */
  437 static uint8_t 
  438 fetch_data_byte(struct x86emu *emu, uint32_t offset)
  439 {
  440         return fetch_byte(emu, get_data_segment(emu), offset);
  441 }
  442 
  443 /*
  444  * PARAMETERS:
  445  * offset       - Offset to load data from
  446  * 
  447  * RETURNS:
  448  * Word value read from the absolute memory location.
  449  * 
  450  * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
  451  */
  452 static uint16_t 
  453 fetch_data_word(struct x86emu *emu, uint32_t offset)
  454 {
  455         return fetch_word(emu, get_data_segment(emu), offset);
  456 }
  457 
  458 /*
  459  * PARAMETERS:
  460  * offset       - Offset to load data from
  461  * 
  462  * RETURNS:
  463  * Long value read from the absolute memory location.
  464  * 
  465  * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
  466  */
  467 static uint32_t 
  468 fetch_data_long(struct x86emu *emu, uint32_t offset)
  469 {
  470         return fetch_long(emu, get_data_segment(emu), offset);
  471 }
  472 
  473 /*
  474  * PARAMETERS:
  475  * segment      - Segment to load data from
  476  * offset       - Offset to load data from
  477  * 
  478  * RETURNS:
  479  * Byte value read from the absolute memory location.
  480  * 
  481  * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
  482  */
  483 static uint8_t 
  484 fetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset)
  485 {
  486         return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
  487 }
  488 
  489 /*
  490  * PARAMETERS:
  491  * segment      - Segment to load data from
  492  * offset       - Offset to load data from
  493  * 
  494  * RETURNS:
  495  * Word value read from the absolute memory location.
  496  * 
  497  * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
  498  */
  499 static uint16_t 
  500 fetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset)
  501 {
  502         return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
  503 }
  504 
  505 /*
  506  * PARAMETERS:
  507  * segment      - Segment to load data from
  508  * offset       - Offset to load data from
  509  * 
  510  * RETURNS:
  511  * Long value read from the absolute memory location.
  512  * 
  513  * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
  514  */
  515 static uint32_t 
  516 fetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset)
  517 {
  518         return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
  519 }
  520 
  521 /*
  522  * PARAMETERS:
  523  * offset       - Offset to store data at
  524  * val          - Value to store
  525  * 
  526  * REMARKS:
  527  * Writes a word value to an segmented memory location. The segment used is
  528  * the current 'default' segment, which may have been overridden.
  529  * 
  530  * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
  531  */
  532 static void 
  533 store_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val)
  534 {
  535         store_byte(emu, get_data_segment(emu), offset, val);
  536 }
  537 
  538 /*
  539  * PARAMETERS:
  540  * offset       - Offset to store data at
  541  * val          - Value to store
  542  * 
  543  * REMARKS:
  544  * Writes a word value to an segmented memory location. The segment used is
  545  * the current 'default' segment, which may have been overridden.
  546  * 
  547  * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
  548  */
  549 static void 
  550 store_data_word(struct x86emu *emu, uint32_t offset, uint16_t val)
  551 {
  552         store_word(emu, get_data_segment(emu), offset, val);
  553 }
  554 
  555 /*
  556  * PARAMETERS:
  557  * offset       - Offset to store data at
  558  * val          - Value to store
  559  * 
  560  * REMARKS:
  561  * Writes a long value to an segmented memory location. The segment used is
  562  * the current 'default' segment, which may have been overridden.
  563  * 
  564  * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
  565  */
  566 static void 
  567 store_data_long(struct x86emu *emu, uint32_t offset, uint32_t val)
  568 {
  569         store_long(emu, get_data_segment(emu), offset, val);
  570 }
  571 
  572 /*
  573  * PARAMETERS:
  574  * segment      - Segment to store data at
  575  * offset       - Offset to store data at
  576  * val          - Value to store
  577  * 
  578  * REMARKS:
  579  * Writes a byte value to an absolute memory location.
  580  * 
  581  * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
  582  */
  583 static void 
  584 store_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val)
  585 {
  586         (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
  587 }
  588 
  589 /*
  590  * PARAMETERS:
  591  * segment      - Segment to store data at
  592  * offset       - Offset to store data at
  593  * val          - Value to store
  594  * 
  595  * REMARKS:
  596  * Writes a word value to an absolute memory location.
  597  * 
  598  * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
  599  */
  600 static void 
  601 store_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val)
  602 {
  603         (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
  604 }
  605 
  606 /*
  607  * PARAMETERS:
  608  * segment      - Segment to store data at
  609  * offset       - Offset to store data at
  610  * val          - Value to store
  611  * 
  612  * REMARKS:
  613  * Writes a long value to an absolute memory location.
  614  * 
  615  * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
  616  */
  617 static void 
  618 store_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val)
  619 {
  620         (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
  621 }
  622 
  623 /*
  624  * PARAMETERS:
  625  * reg  - Register to decode
  626  * 
  627  * RETURNS:
  628  * Pointer to the appropriate register
  629  * 
  630  * REMARKS:
  631  * Return a pointer to the register given by the R/RM field of the
  632  * modrm byte, for byte operands. Also enables the decoding of instructions.
  633  */
  634 static uint8_t *
  635 decode_rm_byte_register(struct x86emu *emu, int reg)
  636 {
  637         switch (reg) {
  638         case 0:
  639                 return &emu->x86.R_AL;
  640         case 1:
  641                 return &emu->x86.R_CL;
  642         case 2:
  643                 return &emu->x86.R_DL;
  644         case 3:
  645                 return &emu->x86.R_BL;
  646         case 4:
  647                 return &emu->x86.R_AH;
  648         case 5:
  649                 return &emu->x86.R_CH;
  650         case 6:
  651                 return &emu->x86.R_DH;
  652         case 7:
  653                 return &emu->x86.R_BH;
  654         default:
  655                 x86emu_halt_sys(emu);
  656         }
  657 }
  658 
  659 static uint8_t *
  660 decode_rl_byte_register(struct x86emu *emu)
  661 {
  662         return decode_rm_byte_register(emu, emu->cur_rl);
  663 }
  664 
  665 static uint8_t *
  666 decode_rh_byte_register(struct x86emu *emu)
  667 {
  668         return decode_rm_byte_register(emu, emu->cur_rh);
  669 }
  670 
  671 /*
  672  * PARAMETERS:
  673  * reg  - Register to decode
  674  * 
  675  * RETURNS:
  676  * Pointer to the appropriate register
  677  * 
  678  * REMARKS:
  679  * Return a pointer to the register given by the R/RM field of the
  680  * modrm byte, for word operands.  Also enables the decoding of instructions.
  681  */
  682 static uint16_t *
  683 decode_rm_word_register(struct x86emu *emu, int reg)
  684 {
  685         switch (reg) {
  686         case 0:
  687                 return &emu->x86.R_AX;
  688         case 1:
  689                 return &emu->x86.R_CX;
  690         case 2:
  691                 return &emu->x86.R_DX;
  692         case 3:
  693                 return &emu->x86.R_BX;
  694         case 4:
  695                 return &emu->x86.R_SP;
  696         case 5:
  697                 return &emu->x86.R_BP;
  698         case 6:
  699                 return &emu->x86.R_SI;
  700         case 7:
  701                 return &emu->x86.R_DI;
  702         default:
  703                 x86emu_halt_sys(emu);
  704         }
  705 }
  706 
  707 static uint16_t *
  708 decode_rl_word_register(struct x86emu *emu)
  709 {
  710         return decode_rm_word_register(emu, emu->cur_rl);
  711 }
  712 
  713 static uint16_t *
  714 decode_rh_word_register(struct x86emu *emu)
  715 {
  716         return decode_rm_word_register(emu, emu->cur_rh);
  717 }
  718 
  719 /*
  720  * PARAMETERS:
  721  * reg  - Register to decode
  722  * 
  723  * RETURNS:
  724  * Pointer to the appropriate register
  725  * 
  726  * REMARKS:
  727  * Return a pointer to the register given by the R/RM field of the
  728  * modrm byte, for dword operands.  Also enables the decoding of instructions.
  729  */
  730 static uint32_t *
  731 decode_rm_long_register(struct x86emu *emu, int reg)
  732 {
  733         switch (reg) {
  734         case 0:
  735                 return &emu->x86.R_EAX;
  736         case 1:
  737                 return &emu->x86.R_ECX;
  738         case 2:
  739                 return &emu->x86.R_EDX;
  740         case 3:
  741                 return &emu->x86.R_EBX;
  742         case 4:
  743                 return &emu->x86.R_ESP;
  744         case 5:
  745                 return &emu->x86.R_EBP;
  746         case 6:
  747                 return &emu->x86.R_ESI;
  748         case 7:
  749                 return &emu->x86.R_EDI;
  750         default:
  751                 x86emu_halt_sys(emu);
  752         }
  753 }
  754 
  755 static uint32_t *
  756 decode_rl_long_register(struct x86emu *emu)
  757 {
  758         return decode_rm_long_register(emu, emu->cur_rl);
  759 }
  760 
  761 static uint32_t *
  762 decode_rh_long_register(struct x86emu *emu)
  763 {
  764         return decode_rm_long_register(emu, emu->cur_rh);
  765 }
  766 
  767 
  768 /*
  769  * PARAMETERS:
  770  * reg  - Register to decode
  771  * 
  772  * RETURNS:
  773  * Pointer to the appropriate register
  774  * 
  775  * REMARKS:
  776  * Return a pointer to the register given by the R/RM field of the
  777  * modrm byte, for word operands, modified from above for the weirdo
  778  * special case of segreg operands.  Also enables the decoding of instructions.
  779  */
  780 static uint16_t *
  781 decode_rh_seg_register(struct x86emu *emu)
  782 {
  783         switch (emu->cur_rh) {
  784         case 0:
  785                 return &emu->x86.R_ES;
  786         case 1:
  787                 return &emu->x86.R_CS;
  788         case 2:
  789                 return &emu->x86.R_SS;
  790         case 3:
  791                 return &emu->x86.R_DS;
  792         case 4:
  793                 return &emu->x86.R_FS;
  794         case 5:
  795                 return &emu->x86.R_GS;
  796         default:
  797                 x86emu_halt_sys(emu);
  798         }
  799 }
  800 
  801 /*
  802  * Return offset from the SIB Byte.
  803  */
  804 static uint32_t 
  805 decode_sib_address(struct x86emu *emu, int sib, int mod)
  806 {
  807         uint32_t base = 0, i = 0, scale = 1;
  808 
  809         switch (sib & 0x07) {
  810         case 0:
  811                 base = emu->x86.R_EAX;
  812                 break;
  813         case 1:
  814                 base = emu->x86.R_ECX;
  815 
  816                 break;
  817         case 2:
  818                 base = emu->x86.R_EDX;
  819                 break;
  820         case 3:
  821                 base = emu->x86.R_EBX;
  822                 break;
  823         case 4:
  824                 base = emu->x86.R_ESP;
  825                 emu->x86.mode |= SYSMODE_SEG_DS_SS;
  826                 break;
  827         case 5:
  828                 if (mod == 0) {
  829                         base = fetch_long_imm(emu);
  830                 } else {
  831                         base = emu->x86.R_EBP;
  832                         emu->x86.mode |= SYSMODE_SEG_DS_SS;
  833                 }
  834                 break;
  835         case 6:
  836                 base = emu->x86.R_ESI;
  837                 break;
  838         case 7:
  839                 base = emu->x86.R_EDI;
  840                 break;
  841         }
  842         switch ((sib >> 3) & 0x07) {
  843         case 0:
  844                 i = emu->x86.R_EAX;
  845                 break;
  846         case 1:
  847                 i = emu->x86.R_ECX;
  848                 break;
  849         case 2:
  850                 i = emu->x86.R_EDX;
  851                 break;
  852         case 3:
  853                 i = emu->x86.R_EBX;
  854                 break;
  855         case 4:
  856                 i = 0;
  857                 break;
  858         case 5:
  859                 i = emu->x86.R_EBP;
  860                 break;
  861         case 6:
  862                 i = emu->x86.R_ESI;
  863                 break;
  864         case 7:
  865                 i = emu->x86.R_EDI;
  866                 break;
  867         }
  868         scale = 1 << ((sib >> 6) & 0x03);
  869         return base + (i * scale);
  870 }
  871 
  872 /*
  873  * PARAMETERS:
  874  * rm   - RM value to decode
  875  * 
  876  * RETURNS:
  877  * Offset in memory for the address decoding
  878  * 
  879  * REMARKS:
  880  * Return the offset given by mod=00, mod=01 or mod=10 addressing.
  881  * Also enables the decoding of instructions.
  882  */
  883 static uint32_t
  884 decode_rl_address(struct x86emu *emu)
  885 {
  886         if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
  887                 uint32_t offset, sib;
  888                 /* 32-bit addressing */
  889                 switch (emu->cur_rl) {
  890                 case 0:
  891                         offset = emu->x86.R_EAX;
  892                         break;
  893                 case 1:
  894                         offset = emu->x86.R_ECX;
  895                         break;
  896                 case 2:
  897                         offset = emu->x86.R_EDX;
  898                         break;
  899                 case 3:
  900                         offset = emu->x86.R_EBX;
  901                         break;
  902                 case 4:
  903                         sib = fetch_byte_imm(emu);
  904                         offset = decode_sib_address(emu, sib, 0);
  905                         break;
  906                 case 5:
  907                         if (emu->cur_mod == 0) {
  908                                 offset = fetch_long_imm(emu);
  909                         } else {
  910                                 emu->x86.mode |= SYSMODE_SEG_DS_SS;
  911                                 offset = emu->x86.R_EBP;
  912                         }
  913                         break;
  914                 case 6:
  915                         offset = emu->x86.R_ESI;
  916                         break;
  917                 case 7:
  918                         offset = emu->x86.R_EDI;
  919                         break;
  920                 default:
  921                         x86emu_halt_sys(emu);
  922                 }
  923                 if (emu->cur_mod == 1)
  924                         offset += (int8_t)fetch_byte_imm(emu);
  925                 else if (emu->cur_mod == 2)
  926                         offset += fetch_long_imm(emu);
  927                 return offset;
  928         } else {
  929                 uint16_t offset;
  930 
  931                 /* 16-bit addressing */
  932                 switch (emu->cur_rl) {
  933                 case 0:
  934                         offset = emu->x86.R_BX + emu->x86.R_SI;
  935                         break;
  936                 case 1:
  937                         offset = emu->x86.R_BX + emu->x86.R_DI;
  938                         break;
  939                 case 2:
  940                         emu->x86.mode |= SYSMODE_SEG_DS_SS;
  941                         offset = emu->x86.R_BP + emu->x86.R_SI;
  942                         break;
  943                 case 3:
  944                         emu->x86.mode |= SYSMODE_SEG_DS_SS;
  945                         offset = emu->x86.R_BP + emu->x86.R_DI;
  946                         break;
  947                 case 4:
  948                         offset = emu->x86.R_SI;
  949                         break;
  950                 case 5:
  951                         offset = emu->x86.R_DI;
  952                         break;
  953                 case 6:
  954                         if (emu->cur_mod == 0) {
  955                                 offset = fetch_word_imm(emu);
  956                         } else {
  957                                 emu->x86.mode |= SYSMODE_SEG_DS_SS;
  958                                 offset = emu->x86.R_BP;
  959                         }
  960                         break;
  961                 case 7:
  962                         offset = emu->x86.R_BX;
  963                         break;
  964                 default:
  965                         x86emu_halt_sys(emu);
  966                 }
  967                 if (emu->cur_mod == 1)
  968                         offset += (int8_t)fetch_byte_imm(emu);
  969                 else if (emu->cur_mod == 2)
  970                         offset += fetch_word_imm(emu);
  971                 return offset;
  972         }
  973 }
  974 
  975 static uint8_t
  976 decode_and_fetch_byte(struct x86emu *emu)
  977 {
  978         if (emu->cur_mod != 3) {
  979                 emu->cur_offset = decode_rl_address(emu);
  980                 return fetch_data_byte(emu, emu->cur_offset);
  981         } else {
  982                 return *decode_rl_byte_register(emu);
  983         }
  984 }
  985 
  986 static uint16_t
  987 decode_and_fetch_word_disp(struct x86emu *emu, int16_t disp)
  988 {
  989         if (emu->cur_mod != 3) {
  990                 /* TODO: A20 gate emulation */
  991                 emu->cur_offset = decode_rl_address(emu) + disp;
  992                 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
  993                         emu->cur_offset &= 0xffff;
  994                 return fetch_data_word(emu, emu->cur_offset);
  995         } else {
  996                 return *decode_rl_word_register(emu);
  997         }
  998 }
  999 
 1000 static uint32_t
 1001 decode_and_fetch_long_disp(struct x86emu *emu, int16_t disp)
 1002 {
 1003         if (emu->cur_mod != 3) {
 1004                 /* TODO: A20 gate emulation */
 1005                 emu->cur_offset = decode_rl_address(emu) + disp;
 1006                 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
 1007                         emu->cur_offset &= 0xffff;
 1008                 return fetch_data_long(emu, emu->cur_offset);
 1009         } else {
 1010                 return *decode_rl_long_register(emu);
 1011         }
 1012 }
 1013 
 1014 uint16_t
 1015 decode_and_fetch_word(struct x86emu *emu)
 1016 {
 1017         return decode_and_fetch_word_disp(emu, 0);
 1018 }
 1019 
 1020 uint32_t
 1021 decode_and_fetch_long(struct x86emu *emu)
 1022 {
 1023         return decode_and_fetch_long_disp(emu, 0);
 1024 }
 1025 
 1026 uint8_t
 1027 decode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm)
 1028 {
 1029         if (emu->cur_mod != 3) {
 1030                 emu->cur_offset = decode_rl_address(emu);
 1031                 *imm = fetch_byte_imm(emu);
 1032                 return fetch_data_byte(emu, emu->cur_offset);
 1033         } else {
 1034                 *imm = fetch_byte_imm(emu);
 1035                 return *decode_rl_byte_register(emu);
 1036         }
 1037 }
 1038 
 1039 static uint16_t
 1040 decode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm)
 1041 {
 1042         if (emu->cur_mod != 3) {
 1043                 emu->cur_offset = decode_rl_address(emu);
 1044                 *imm = fetch_byte_imm(emu);
 1045                 return fetch_data_word(emu, emu->cur_offset);
 1046         } else {
 1047                 *imm = fetch_byte_imm(emu);
 1048                 return *decode_rl_word_register(emu);
 1049         }
 1050 }
 1051 
 1052 static uint32_t
 1053 decode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm)
 1054 {
 1055         if (emu->cur_mod != 3) {
 1056                 emu->cur_offset = decode_rl_address(emu);
 1057                 *imm = fetch_byte_imm(emu);
 1058                 return fetch_data_long(emu, emu->cur_offset);
 1059         } else {
 1060                 *imm = fetch_byte_imm(emu);
 1061                 return *decode_rl_long_register(emu);
 1062         }
 1063 }
 1064 
 1065 static void
 1066 write_back_byte(struct x86emu *emu, uint8_t val)
 1067 {
 1068         if (emu->cur_mod != 3)
 1069                 store_data_byte(emu, emu->cur_offset, val);
 1070         else
 1071                 *decode_rl_byte_register(emu) = val;
 1072 }
 1073 
 1074 static void
 1075 write_back_word(struct x86emu *emu, uint16_t val)
 1076 {
 1077         if (emu->cur_mod != 3)
 1078                 store_data_word(emu, emu->cur_offset, val);
 1079         else
 1080                 *decode_rl_word_register(emu) = val;
 1081 }
 1082 
 1083 static void
 1084 write_back_long(struct x86emu *emu, uint32_t val)
 1085 {
 1086         if (emu->cur_mod != 3)
 1087                 store_data_long(emu, emu->cur_offset, val);
 1088         else
 1089                 *decode_rl_long_register(emu) = val;
 1090 }
 1091 
 1092 static void
 1093 common_inc_word_long(struct x86emu *emu, union x86emu_register *reg)
 1094 {
 1095         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1096                 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
 1097         else
 1098                 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
 1099 }
 1100 
 1101 static void
 1102 common_dec_word_long(struct x86emu *emu, union x86emu_register *reg)
 1103 {
 1104         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1105                 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
 1106         else
 1107                 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
 1108 }
 1109 
 1110 static void
 1111 common_binop_byte_rm_r(struct x86emu *emu, 
 1112     uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
 1113 {
 1114         uint32_t destoffset;
 1115         uint8_t *destreg, srcval;
 1116         uint8_t destval;
 1117 
 1118         fetch_decode_modrm(emu);
 1119         srcval = *decode_rh_byte_register(emu);
 1120         if (emu->cur_mod != 3) {
 1121                 destoffset = decode_rl_address(emu);
 1122                 destval = fetch_data_byte(emu, destoffset);
 1123                 destval = (*binop)(emu, destval, srcval);
 1124                 store_data_byte(emu, destoffset, destval);
 1125         } else {
 1126                 destreg = decode_rl_byte_register(emu);
 1127                 *destreg = (*binop)(emu, *destreg, srcval);
 1128         }
 1129 }
 1130 
 1131 static void
 1132 common_binop_ns_byte_rm_r(struct x86emu *emu, 
 1133     void (*binop)(struct x86emu *, uint8_t, uint8_t))
 1134 {
 1135         uint32_t destoffset;
 1136         uint8_t destval, srcval;
 1137 
 1138         fetch_decode_modrm(emu);
 1139         srcval = *decode_rh_byte_register(emu);
 1140         if (emu->cur_mod != 3) {
 1141                 destoffset = decode_rl_address(emu);
 1142                 destval = fetch_data_byte(emu, destoffset);
 1143         } else {
 1144                 destval = *decode_rl_byte_register(emu);
 1145         }
 1146         (*binop)(emu, destval, srcval);
 1147 }
 1148 
 1149 static void
 1150 common_binop_word_rm_r(struct x86emu *emu,
 1151     uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
 1152 {
 1153         uint32_t destoffset;
 1154         uint16_t destval, *destreg, srcval;
 1155 
 1156         fetch_decode_modrm(emu);
 1157         srcval = *decode_rh_word_register(emu);
 1158         if (emu->cur_mod != 3) {
 1159                 destoffset = decode_rl_address(emu);
 1160                 destval = fetch_data_word(emu, destoffset);
 1161                 destval = (*binop)(emu, destval, srcval);
 1162                 store_data_word(emu, destoffset, destval);
 1163         } else {
 1164                 destreg = decode_rl_word_register(emu);
 1165                 *destreg = (*binop)(emu, *destreg, srcval);
 1166         }
 1167 }
 1168 
 1169 static void
 1170 common_binop_byte_r_rm(struct x86emu *emu,
 1171     uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
 1172 {
 1173         uint8_t *destreg, srcval;
 1174         uint32_t srcoffset;
 1175 
 1176         fetch_decode_modrm(emu);
 1177         destreg = decode_rh_byte_register(emu);
 1178         if (emu->cur_mod != 3) {
 1179                 srcoffset = decode_rl_address(emu);
 1180                 srcval = fetch_data_byte(emu, srcoffset);
 1181         } else {
 1182                 srcval = *decode_rl_byte_register(emu);
 1183         }
 1184         *destreg = (*binop)(emu, *destreg, srcval);
 1185 }
 1186 
 1187 static void
 1188 common_binop_long_rm_r(struct x86emu *emu,
 1189     uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
 1190 {
 1191         uint32_t destoffset;
 1192         uint32_t destval, *destreg, srcval;
 1193 
 1194         fetch_decode_modrm(emu);
 1195         srcval = *decode_rh_long_register(emu);
 1196         if (emu->cur_mod != 3) {
 1197                 destoffset = decode_rl_address(emu);
 1198                 destval = fetch_data_long(emu, destoffset);
 1199                 destval = (*binop)(emu, destval, srcval);
 1200                 store_data_long(emu, destoffset, destval);
 1201         } else {
 1202                 destreg = decode_rl_long_register(emu);
 1203                 *destreg = (*binop)(emu, *destreg, srcval);
 1204         }
 1205 }
 1206 
 1207 static void
 1208 common_binop_word_long_rm_r(struct x86emu *emu,
 1209     uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
 1210     uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
 1211 {
 1212         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1213                 common_binop_long_rm_r(emu, binop32);
 1214         else
 1215                 common_binop_word_rm_r(emu, binop16);
 1216 }
 1217 
 1218 static void
 1219 common_binop_ns_word_rm_r(struct x86emu *emu,
 1220     void (*binop)(struct x86emu *, uint16_t, uint16_t))
 1221 {
 1222         uint32_t destoffset;
 1223         uint16_t destval, srcval;
 1224 
 1225         fetch_decode_modrm(emu);
 1226         srcval = *decode_rh_word_register(emu);
 1227         if (emu->cur_mod != 3) {
 1228                 destoffset = decode_rl_address(emu);
 1229                 destval = fetch_data_word(emu, destoffset);
 1230         } else {
 1231                 destval = *decode_rl_word_register(emu);
 1232         }
 1233         (*binop)(emu, destval, srcval);
 1234 }
 1235 
 1236 
 1237 static void
 1238 common_binop_ns_long_rm_r(struct x86emu *emu,
 1239     void (*binop)(struct x86emu *, uint32_t, uint32_t))
 1240 {
 1241         uint32_t destoffset;
 1242         uint32_t destval, srcval;
 1243 
 1244         fetch_decode_modrm(emu);
 1245         srcval = *decode_rh_long_register(emu);
 1246         if (emu->cur_mod != 3) {
 1247                 destoffset = decode_rl_address(emu);
 1248                 destval = fetch_data_long(emu, destoffset);
 1249         } else {
 1250                 destval = *decode_rl_long_register(emu);
 1251         }
 1252         (*binop)(emu, destval, srcval);
 1253 }
 1254 
 1255 static void
 1256 common_binop_ns_word_long_rm_r(struct x86emu *emu,
 1257     void (*binop16)(struct x86emu *, uint16_t, uint16_t),
 1258     void (*binop32)(struct x86emu *, uint32_t, uint32_t))
 1259 {
 1260         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1261                 common_binop_ns_long_rm_r(emu, binop32);
 1262         else
 1263                 common_binop_ns_word_rm_r(emu, binop16);
 1264 }
 1265 
 1266 static void
 1267 common_binop_long_r_rm(struct x86emu *emu,
 1268     uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
 1269 {
 1270         uint32_t srcoffset;
 1271         uint32_t *destreg, srcval;
 1272 
 1273         fetch_decode_modrm(emu);
 1274         destreg = decode_rh_long_register(emu);
 1275         if (emu->cur_mod != 3) {
 1276                 srcoffset = decode_rl_address(emu);
 1277                 srcval = fetch_data_long(emu, srcoffset);
 1278         } else {
 1279                 srcval = *decode_rl_long_register(emu);
 1280         }
 1281         *destreg = (*binop)(emu, *destreg, srcval);
 1282 }
 1283 
 1284 static void
 1285 common_binop_word_r_rm(struct x86emu *emu,
 1286     uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
 1287 {
 1288         uint32_t srcoffset;
 1289         uint16_t *destreg, srcval;
 1290 
 1291         fetch_decode_modrm(emu);
 1292         destreg = decode_rh_word_register(emu);
 1293         if (emu->cur_mod != 3) {
 1294                 srcoffset = decode_rl_address(emu);
 1295                 srcval = fetch_data_word(emu, srcoffset);
 1296         } else {
 1297                 srcval = *decode_rl_word_register(emu);
 1298         }
 1299         *destreg = (*binop)(emu, *destreg, srcval);
 1300 }
 1301 
 1302 static void
 1303 common_binop_word_long_r_rm(struct x86emu *emu,
 1304     uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
 1305     uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
 1306 {
 1307         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1308                 common_binop_long_r_rm(emu, binop32);
 1309         else
 1310                 common_binop_word_r_rm(emu, binop16);
 1311 }
 1312 
 1313 static void
 1314 common_binop_byte_imm(struct x86emu *emu,
 1315     uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
 1316 {
 1317         uint8_t srcval;
 1318 
 1319         srcval = fetch_byte_imm(emu);
 1320         emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
 1321 }
 1322 
 1323 static void
 1324 common_binop_word_long_imm(struct x86emu *emu,
 1325     uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
 1326     uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
 1327 {
 1328         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1329                 uint32_t srcval;
 1330 
 1331                 srcval = fetch_long_imm(emu);
 1332                 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
 1333         } else {
 1334                 uint16_t srcval;
 1335 
 1336                 srcval = fetch_word_imm(emu);
 1337                 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
 1338         }
 1339 }
 1340 
 1341 static void
 1342 common_push_word_long(struct x86emu *emu, union x86emu_register *reg)
 1343 {
 1344         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1345                 push_long(emu, reg->I32_reg.e_reg);
 1346         else
 1347                 push_word(emu, reg->I16_reg.x_reg);
 1348 }
 1349 
 1350 static void
 1351 common_pop_word_long(struct x86emu *emu, union x86emu_register *reg)
 1352 {
 1353         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1354                 reg->I32_reg.e_reg = pop_long(emu);
 1355         else
 1356                 reg->I16_reg.x_reg = pop_word(emu);
 1357 }
 1358 
 1359 static void
 1360 common_imul_long_IMM(struct x86emu *emu, int byte_imm)
 1361 {
 1362         uint32_t srcoffset;
 1363         uint32_t *destreg, srcval;
 1364         int32_t imm;
 1365         uint64_t res;
 1366 
 1367         fetch_decode_modrm(emu);
 1368         destreg = decode_rh_long_register(emu);
 1369         if (emu->cur_mod != 3) {
 1370                 srcoffset = decode_rl_address(emu);
 1371                 srcval = fetch_data_long(emu, srcoffset);
 1372         } else {
 1373                 srcval = *decode_rl_long_register(emu);
 1374         }
 1375 
 1376         if (byte_imm)
 1377                 imm = (int8_t)fetch_byte_imm(emu);
 1378         else
 1379                 imm = fetch_long_imm(emu);
 1380         res = (int32_t)srcval * imm;
 1381 
 1382         if (res > 0xffffffff) {
 1383                 SET_FLAG(F_CF);
 1384                 SET_FLAG(F_OF);
 1385         } else {
 1386                 CLEAR_FLAG(F_CF);
 1387                 CLEAR_FLAG(F_OF);
 1388         }
 1389         *destreg = (uint32_t)res;
 1390 }
 1391 
 1392 static void
 1393 common_imul_word_IMM(struct x86emu *emu, int byte_imm)
 1394 {
 1395         uint32_t srcoffset;
 1396         uint16_t *destreg, srcval;
 1397         int16_t imm;
 1398         uint32_t res;
 1399 
 1400         fetch_decode_modrm(emu);
 1401         destreg = decode_rh_word_register(emu);
 1402         if (emu->cur_mod != 3) {
 1403                 srcoffset = decode_rl_address(emu);
 1404                 srcval = fetch_data_word(emu, srcoffset);
 1405         } else {
 1406                 srcval = *decode_rl_word_register(emu);
 1407         }
 1408 
 1409         if (byte_imm)
 1410                 imm = (int8_t)fetch_byte_imm(emu);
 1411         else
 1412                 imm = fetch_word_imm(emu);
 1413         res = (int16_t)srcval * imm;
 1414 
 1415         if (res > 0xffff) {
 1416                 SET_FLAG(F_CF);
 1417                 SET_FLAG(F_OF);
 1418         } else {
 1419                 CLEAR_FLAG(F_CF);
 1420                 CLEAR_FLAG(F_OF);
 1421         }
 1422         *destreg = (uint16_t) res;
 1423 }
 1424 
 1425 static void
 1426 common_imul_imm(struct x86emu *emu, int byte_imm)
 1427 {
 1428         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1429                 common_imul_long_IMM(emu, byte_imm);
 1430         else
 1431                 common_imul_word_IMM(emu, byte_imm);
 1432 }
 1433 
 1434 static void
 1435 common_jmp_near(struct x86emu *emu, int cond)
 1436 {
 1437         int8_t offset;
 1438         uint16_t target;
 1439 
 1440         offset = (int8_t) fetch_byte_imm(emu);
 1441         target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
 1442         if (cond)
 1443                 emu->x86.R_IP = target;
 1444 }
 1445 
 1446 static void
 1447 common_load_far_pointer(struct x86emu *emu, uint16_t *seg)
 1448 {
 1449         uint16_t *dstreg;
 1450         uint32_t srcoffset;
 1451 
 1452         fetch_decode_modrm(emu);
 1453         if (emu->cur_mod == 3)
 1454                 x86emu_halt_sys(emu);
 1455 
 1456         dstreg = decode_rh_word_register(emu);
 1457         srcoffset = decode_rl_address(emu);
 1458         *dstreg = fetch_data_word(emu, srcoffset);
 1459         *seg = fetch_data_word(emu, srcoffset + 2);
 1460 }
 1461 
 1462 /* Implementation */
 1463 
 1464 /*
 1465  * REMARKS:
 1466  * Handles opcode 0x3a
 1467  */
 1468 static void
 1469 x86emuOp_cmp_byte_R_RM(struct x86emu *emu)
 1470 {
 1471         uint8_t *destreg, srcval;
 1472 
 1473         fetch_decode_modrm(emu);
 1474         destreg = decode_rh_byte_register(emu);
 1475         srcval = decode_and_fetch_byte(emu);
 1476         cmp_byte(emu, *destreg, srcval);
 1477 }
 1478 
 1479 /*
 1480  * REMARKS:
 1481  * 
 1482  * Handles opcode 0x3b
 1483  */
 1484 static void
 1485 x86emuOp32_cmp_word_R_RM(struct x86emu *emu)
 1486 {
 1487         uint32_t srcval, *destreg;
 1488 
 1489         fetch_decode_modrm(emu);
 1490         destreg = decode_rh_long_register(emu);
 1491         srcval = decode_and_fetch_long(emu);
 1492         cmp_long(emu, *destreg, srcval);
 1493 }
 1494 
 1495 static void
 1496 x86emuOp16_cmp_word_R_RM(struct x86emu *emu)
 1497 {
 1498         uint16_t srcval, *destreg;
 1499 
 1500         fetch_decode_modrm(emu);
 1501         destreg = decode_rh_word_register(emu);
 1502         srcval = decode_and_fetch_word(emu);
 1503         cmp_word(emu, *destreg, srcval);
 1504 }
 1505 
 1506 static void
 1507 x86emuOp_cmp_word_R_RM(struct x86emu *emu)
 1508 {
 1509         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1510                 x86emuOp32_cmp_word_R_RM(emu);
 1511         else
 1512                 x86emuOp16_cmp_word_R_RM(emu);
 1513 }
 1514 
 1515 /*
 1516  * REMARKS:
 1517  * Handles opcode 0x3c
 1518  */
 1519 static void
 1520 x86emuOp_cmp_byte_AL_IMM(struct x86emu *emu)
 1521 {
 1522         uint8_t srcval;
 1523 
 1524         srcval = fetch_byte_imm(emu);
 1525         cmp_byte(emu, emu->x86.R_AL, srcval);
 1526 }
 1527 
 1528 /*
 1529  * REMARKS:
 1530  * Handles opcode 0x3d
 1531  */
 1532 static void
 1533 x86emuOp32_cmp_word_AX_IMM(struct x86emu *emu)
 1534 {
 1535         uint32_t srcval;
 1536 
 1537         srcval = fetch_long_imm(emu);
 1538         cmp_long(emu, emu->x86.R_EAX, srcval);
 1539 }
 1540 
 1541 static void
 1542 x86emuOp16_cmp_word_AX_IMM(struct x86emu *emu)
 1543 {
 1544         uint16_t srcval;
 1545 
 1546         srcval = fetch_word_imm(emu);
 1547         cmp_word(emu, emu->x86.R_AX, srcval);
 1548 }
 1549 
 1550 static void
 1551 x86emuOp_cmp_word_AX_IMM(struct x86emu *emu)
 1552 {
 1553         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1554                 x86emuOp32_cmp_word_AX_IMM(emu);
 1555         else
 1556                 x86emuOp16_cmp_word_AX_IMM(emu);
 1557 }
 1558 
 1559 /*
 1560  * REMARKS:
 1561  * Handles opcode 0x60
 1562  */
 1563 static void
 1564 x86emuOp_push_all(struct x86emu *emu)
 1565 {
 1566         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1567                 uint32_t old_sp = emu->x86.R_ESP;
 1568 
 1569                 push_long(emu, emu->x86.R_EAX);
 1570                 push_long(emu, emu->x86.R_ECX);
 1571                 push_long(emu, emu->x86.R_EDX);
 1572                 push_long(emu, emu->x86.R_EBX);
 1573                 push_long(emu, old_sp);
 1574                 push_long(emu, emu->x86.R_EBP);
 1575                 push_long(emu, emu->x86.R_ESI);
 1576                 push_long(emu, emu->x86.R_EDI);
 1577         } else {
 1578                 uint16_t old_sp = emu->x86.R_SP;
 1579 
 1580                 push_word(emu, emu->x86.R_AX);
 1581                 push_word(emu, emu->x86.R_CX);
 1582                 push_word(emu, emu->x86.R_DX);
 1583                 push_word(emu, emu->x86.R_BX);
 1584                 push_word(emu, old_sp);
 1585                 push_word(emu, emu->x86.R_BP);
 1586                 push_word(emu, emu->x86.R_SI);
 1587                 push_word(emu, emu->x86.R_DI);
 1588         }
 1589 }
 1590 
 1591 /*
 1592  * REMARKS:
 1593  * Handles opcode 0x61
 1594  */
 1595 static void
 1596 x86emuOp_pop_all(struct x86emu *emu)
 1597 {
 1598         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1599                 emu->x86.R_EDI = pop_long(emu);
 1600                 emu->x86.R_ESI = pop_long(emu);
 1601                 emu->x86.R_EBP = pop_long(emu);
 1602                 emu->x86.R_ESP += 4;    /* skip ESP */
 1603                 emu->x86.R_EBX = pop_long(emu);
 1604                 emu->x86.R_EDX = pop_long(emu);
 1605                 emu->x86.R_ECX = pop_long(emu);
 1606                 emu->x86.R_EAX = pop_long(emu);
 1607         } else {
 1608                 emu->x86.R_DI = pop_word(emu);
 1609                 emu->x86.R_SI = pop_word(emu);
 1610                 emu->x86.R_BP = pop_word(emu);
 1611                 emu->x86.R_SP += 2;/* skip SP */
 1612                 emu->x86.R_BX = pop_word(emu);
 1613                 emu->x86.R_DX = pop_word(emu);
 1614                 emu->x86.R_CX = pop_word(emu);
 1615                 emu->x86.R_AX = pop_word(emu);
 1616         }
 1617 }
 1618 /*opcode 0x62   ILLEGAL OP, calls x86emuOp_illegal_op() */
 1619 /*opcode 0x63   ILLEGAL OP, calls x86emuOp_illegal_op() */
 1620 
 1621 
 1622 /*
 1623  * REMARKS:
 1624  * Handles opcode 0x68
 1625  */
 1626 static void
 1627 x86emuOp_push_word_IMM(struct x86emu *emu)
 1628 {
 1629         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1630                 uint32_t imm;
 1631 
 1632                 imm = fetch_long_imm(emu);
 1633                 push_long(emu, imm);
 1634         } else {
 1635                 uint16_t imm;
 1636 
 1637                 imm = fetch_word_imm(emu);
 1638                 push_word(emu, imm);
 1639         }
 1640 }
 1641 
 1642 /*
 1643  * REMARKS:
 1644  * Handles opcode 0x6a
 1645  */
 1646 static void
 1647 x86emuOp_push_byte_IMM(struct x86emu *emu)
 1648 {
 1649         int16_t imm;
 1650 
 1651         imm = (int8_t) fetch_byte_imm(emu);
 1652         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1653                 push_long(emu, (int32_t) imm);
 1654         } else {
 1655                 push_word(emu, imm);
 1656         }
 1657 }
 1658 
 1659 /*
 1660  * REMARKS:
 1661  * Handles opcode 0x6c and 0x6d
 1662  */
 1663 static void
 1664 x86emuOp_ins_word(struct x86emu *emu)
 1665 {
 1666         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1667                 ins(emu, 4);
 1668         } else {
 1669                 ins(emu, 2);
 1670         }
 1671 }
 1672 
 1673 /*
 1674  * REMARKS:
 1675  * Handles opcode 0x6f
 1676  */
 1677 static void
 1678 x86emuOp_outs_word(struct x86emu *emu)
 1679 {
 1680         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 1681                 outs(emu, 4);
 1682         } else {
 1683                 outs(emu, 2);
 1684         }
 1685 }
 1686 
 1687 /*
 1688  * REMARKS:
 1689  * Handles opcode 0x7c
 1690  */
 1691 static void
 1692 x86emuOp_jump_near_L(struct x86emu *emu)
 1693 {
 1694         int sf, of;
 1695 
 1696         sf = ACCESS_FLAG(F_SF) != 0;
 1697         of = ACCESS_FLAG(F_OF) != 0;
 1698 
 1699         common_jmp_near(emu, sf != of);
 1700 }
 1701 
 1702 /*
 1703  * REMARKS:
 1704  * Handles opcode 0x7d
 1705  */
 1706 static void
 1707 x86emuOp_jump_near_NL(struct x86emu *emu)
 1708 {
 1709         int sf, of;
 1710 
 1711         sf = ACCESS_FLAG(F_SF) != 0;
 1712         of = ACCESS_FLAG(F_OF) != 0;
 1713 
 1714         common_jmp_near(emu, sf == of);
 1715 }
 1716 
 1717 /*
 1718  * REMARKS:
 1719  * Handles opcode 0x7e
 1720  */
 1721 static void
 1722 x86emuOp_jump_near_LE(struct x86emu *emu)
 1723 {
 1724         int sf, of;
 1725 
 1726         sf = ACCESS_FLAG(F_SF) != 0;
 1727         of = ACCESS_FLAG(F_OF) != 0;
 1728 
 1729         common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
 1730 }
 1731 
 1732 /*
 1733  * REMARKS:
 1734  * Handles opcode 0x7f
 1735  */
 1736 static void
 1737 x86emuOp_jump_near_NLE(struct x86emu *emu)
 1738 {
 1739         int sf, of;
 1740 
 1741         sf = ACCESS_FLAG(F_SF) != 0;
 1742         of = ACCESS_FLAG(F_OF) != 0;
 1743 
 1744         common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
 1745 }
 1746 
 1747 static
 1748 uint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) =
 1749 {
 1750         add_byte,               /* 00 */
 1751         or_byte,                /* 01 */
 1752         adc_byte,               /* 02 */
 1753         sbb_byte,               /* 03 */
 1754         and_byte,               /* 04 */
 1755         sub_byte,               /* 05 */
 1756         xor_byte,               /* 06 */
 1757         cmp_byte,               /* 07 */
 1758 };
 1759 
 1760 /*
 1761  * REMARKS:
 1762  * Handles opcode 0x80
 1763  */
 1764 static void
 1765 x86emuOp_opc80_byte_RM_IMM(struct x86emu *emu)
 1766 {
 1767         uint8_t imm, destval;
 1768 
 1769         /*
 1770          * Weirdo special case instruction format.  Part of the opcode
 1771          * held below in "RH".  Doubly nested case would result, except
 1772          * that the decoded instruction
 1773          */
 1774         fetch_decode_modrm(emu);
 1775         destval = decode_and_fetch_byte(emu);
 1776         imm = fetch_byte_imm(emu);
 1777         destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
 1778         if (emu->cur_rh != 7)
 1779                 write_back_byte(emu, destval);
 1780 }
 1781 
 1782 static
 1783 uint16_t(* const opc81_word_operation[])
 1784     (struct x86emu *, uint16_t d, uint16_t s) =
 1785 {
 1786         add_word,               /* 00 */
 1787         or_word,                /* 01 */
 1788         adc_word,               /* 02 */
 1789         sbb_word,               /* 03 */
 1790         and_word,               /* 04 */
 1791         sub_word,               /* 05 */
 1792         xor_word,               /* 06 */
 1793         cmp_word,               /* 07 */
 1794 };
 1795 
 1796 static
 1797 uint32_t(* const opc81_long_operation[])
 1798     (struct x86emu *, uint32_t d, uint32_t s) =
 1799 {
 1800         add_long,               /* 00 */
 1801         or_long,                /* 01 */
 1802         adc_long,               /* 02 */
 1803         sbb_long,               /* 03 */
 1804         and_long,               /* 04 */
 1805         sub_long,               /* 05 */
 1806         xor_long,               /* 06 */
 1807         cmp_long,               /* 07 */
 1808 };
 1809 
 1810 /*
 1811  * REMARKS:
 1812  * Handles opcode 0x81
 1813  */
 1814 static void
 1815 x86emuOp32_opc81_word_RM_IMM(struct x86emu *emu)
 1816 {
 1817         uint32_t destval, imm;
 1818 
 1819         /*
 1820          * Weirdo special case instruction format.  Part of the opcode
 1821          * held below in "RH".  Doubly nested case would result, except
 1822          * that the decoded instruction
 1823          */
 1824         fetch_decode_modrm(emu);
 1825         destval = decode_and_fetch_long(emu);
 1826         imm = fetch_long_imm(emu);
 1827         destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
 1828         if (emu->cur_rh != 7)
 1829                 write_back_long(emu, destval);
 1830 }
 1831 
 1832 static void
 1833 x86emuOp16_opc81_word_RM_IMM(struct x86emu *emu)
 1834 {
 1835         uint16_t destval, imm;
 1836 
 1837         /*
 1838          * Weirdo special case instruction format.  Part of the opcode
 1839          * held below in "RH".  Doubly nested case would result, except
 1840          * that the decoded instruction
 1841          */
 1842         fetch_decode_modrm(emu);
 1843         destval = decode_and_fetch_word(emu);
 1844         imm = fetch_word_imm(emu);
 1845         destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
 1846         if (emu->cur_rh != 7)
 1847                 write_back_word(emu, destval);
 1848 }
 1849 
 1850 static void
 1851 x86emuOp_opc81_word_RM_IMM(struct x86emu *emu)
 1852 {
 1853         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1854                 x86emuOp32_opc81_word_RM_IMM(emu);
 1855         else
 1856                 x86emuOp16_opc81_word_RM_IMM(emu);
 1857 }
 1858 
 1859 static
 1860 uint8_t(* const opc82_byte_operation[])
 1861     (struct x86emu *, uint8_t s, uint8_t d) =
 1862 {
 1863         add_byte,               /* 00 */
 1864         or_byte,                /* 01 *//* YYY UNUSED ???? */
 1865         adc_byte,               /* 02 */
 1866         sbb_byte,               /* 03 */
 1867         and_byte,               /* 04 *//* YYY UNUSED ???? */
 1868         sub_byte,               /* 05 */
 1869         xor_byte,               /* 06 *//* YYY UNUSED ???? */
 1870         cmp_byte,               /* 07 */
 1871 };
 1872 
 1873 /*
 1874  * REMARKS:
 1875  * Handles opcode 0x82
 1876  */
 1877 static void
 1878 x86emuOp_opc82_byte_RM_IMM(struct x86emu *emu)
 1879 {
 1880         uint8_t imm, destval;
 1881 
 1882         /*
 1883          * Weirdo special case instruction format.  Part of the opcode
 1884          * held below in "RH".  Doubly nested case would result, except
 1885          * that the decoded instruction Similar to opcode 81, except that
 1886          * the immediate byte is sign extended to a word length.
 1887          */
 1888         fetch_decode_modrm(emu);
 1889         destval = decode_and_fetch_byte(emu);
 1890         imm = fetch_byte_imm(emu);
 1891         destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
 1892         if (emu->cur_rh != 7)
 1893                 write_back_byte(emu, destval);
 1894 }
 1895 
 1896 static
 1897 uint16_t(* const opc83_word_operation[])
 1898     (struct x86emu *, uint16_t s, uint16_t d) =
 1899 {
 1900         add_word,               /* 00 */
 1901         or_word,                /* 01 *//* YYY UNUSED ???? */
 1902         adc_word,               /* 02 */
 1903         sbb_word,               /* 03 */
 1904         and_word,               /* 04 *//* YYY UNUSED ???? */
 1905         sub_word,               /* 05 */
 1906         xor_word,               /* 06 *//* YYY UNUSED ???? */
 1907         cmp_word,               /* 07 */
 1908 };
 1909 
 1910 static
 1911 uint32_t(* const opc83_long_operation[])
 1912     (struct x86emu *, uint32_t s, uint32_t d) =
 1913 {
 1914         add_long,               /* 00 */
 1915         or_long,                /* 01 *//* YYY UNUSED ???? */
 1916         adc_long,               /* 02 */
 1917         sbb_long,               /* 03 */
 1918         and_long,               /* 04 *//* YYY UNUSED ???? */
 1919         sub_long,               /* 05 */
 1920         xor_long,               /* 06 *//* YYY UNUSED ???? */
 1921         cmp_long,               /* 07 */
 1922 };
 1923 
 1924 /*
 1925  * REMARKS:
 1926  * Handles opcode 0x83
 1927  */
 1928 static void
 1929 x86emuOp32_opc83_word_RM_IMM(struct x86emu *emu)
 1930 {
 1931         uint32_t destval, imm;
 1932 
 1933         fetch_decode_modrm(emu);
 1934         destval = decode_and_fetch_long(emu);
 1935         imm = (int8_t) fetch_byte_imm(emu);
 1936         destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
 1937         if (emu->cur_rh != 7)
 1938                 write_back_long(emu, destval);
 1939 }
 1940 
 1941 static void
 1942 x86emuOp16_opc83_word_RM_IMM(struct x86emu *emu)
 1943 {
 1944         uint16_t destval, imm;
 1945 
 1946         fetch_decode_modrm(emu);
 1947         destval = decode_and_fetch_word(emu);
 1948         imm = (int8_t) fetch_byte_imm(emu);
 1949         destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
 1950         if (emu->cur_rh != 7)
 1951                 write_back_word(emu, destval);
 1952 }
 1953 
 1954 static void
 1955 x86emuOp_opc83_word_RM_IMM(struct x86emu *emu)
 1956 {
 1957         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 1958                 x86emuOp32_opc83_word_RM_IMM(emu);
 1959         else
 1960                 x86emuOp16_opc83_word_RM_IMM(emu);
 1961 }
 1962 
 1963 /*
 1964  * REMARKS:
 1965  * Handles opcode 0x86
 1966  */
 1967 static void
 1968 x86emuOp_xchg_byte_RM_R(struct x86emu *emu)
 1969 {
 1970         uint8_t *srcreg, destval, tmp;
 1971 
 1972         fetch_decode_modrm(emu);
 1973         destval = decode_and_fetch_byte(emu);
 1974         srcreg = decode_rh_byte_register(emu);
 1975         tmp = destval;
 1976         destval = *srcreg;
 1977         *srcreg = tmp;
 1978         write_back_byte(emu, destval);
 1979 }
 1980 
 1981 /*
 1982  * REMARKS:
 1983  * Handles opcode 0x87
 1984  */
 1985 static void
 1986 x86emuOp32_xchg_word_RM_R(struct x86emu *emu)
 1987 {
 1988         uint32_t *srcreg, destval, tmp;
 1989 
 1990         fetch_decode_modrm(emu);
 1991         destval = decode_and_fetch_long(emu);
 1992         srcreg = decode_rh_long_register(emu);
 1993         tmp = destval;
 1994         destval = *srcreg;
 1995         *srcreg = tmp;
 1996         write_back_long(emu, destval);
 1997 }
 1998 
 1999 static void
 2000 x86emuOp16_xchg_word_RM_R(struct x86emu *emu)
 2001 {
 2002         uint16_t *srcreg, destval, tmp;
 2003 
 2004         fetch_decode_modrm(emu);
 2005         destval = decode_and_fetch_word(emu);
 2006         srcreg = decode_rh_word_register(emu);
 2007         tmp = destval;
 2008         destval = *srcreg;
 2009         *srcreg = tmp;
 2010         write_back_word(emu, destval);
 2011 }
 2012 
 2013 static void
 2014 x86emuOp_xchg_word_RM_R(struct x86emu *emu)
 2015 {
 2016         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2017                 x86emuOp32_xchg_word_RM_R(emu);
 2018         else
 2019                 x86emuOp16_xchg_word_RM_R(emu);
 2020 }
 2021 
 2022 /*
 2023  * REMARKS:
 2024  * Handles opcode 0x88
 2025  */
 2026 static void
 2027 x86emuOp_mov_byte_RM_R(struct x86emu *emu)
 2028 {
 2029         uint8_t *destreg, *srcreg;
 2030         uint32_t destoffset;
 2031 
 2032         fetch_decode_modrm(emu);
 2033         srcreg = decode_rh_byte_register(emu);
 2034         if (emu->cur_mod != 3) {
 2035                 destoffset = decode_rl_address(emu);
 2036                 store_data_byte(emu, destoffset, *srcreg);
 2037         } else {
 2038                 destreg = decode_rl_byte_register(emu);
 2039                 *destreg = *srcreg;
 2040         }
 2041 }
 2042 
 2043 /*
 2044  * REMARKS:
 2045  * Handles opcode 0x89
 2046  */
 2047 static void
 2048 x86emuOp32_mov_word_RM_R(struct x86emu *emu)
 2049 {
 2050         uint32_t destoffset;
 2051         uint32_t *destreg, srcval;
 2052 
 2053         fetch_decode_modrm(emu);
 2054         srcval = *decode_rh_long_register(emu);
 2055         if (emu->cur_mod != 3) {
 2056                 destoffset = decode_rl_address(emu);
 2057                 store_data_long(emu, destoffset, srcval);
 2058         } else {
 2059                 destreg = decode_rl_long_register(emu);
 2060                 *destreg = srcval;
 2061         }
 2062 }
 2063 
 2064 static void
 2065 x86emuOp16_mov_word_RM_R(struct x86emu *emu)
 2066 {
 2067         uint32_t destoffset;
 2068         uint16_t *destreg, srcval;
 2069 
 2070         fetch_decode_modrm(emu);
 2071         srcval = *decode_rh_word_register(emu);
 2072         if (emu->cur_mod != 3) {
 2073                 destoffset = decode_rl_address(emu);
 2074                 store_data_word(emu, destoffset, srcval);
 2075         } else {
 2076                 destreg = decode_rl_word_register(emu);
 2077                 *destreg = srcval;
 2078         }
 2079 }
 2080 
 2081 static void
 2082 x86emuOp_mov_word_RM_R(struct x86emu *emu)
 2083 {
 2084         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2085                 x86emuOp32_mov_word_RM_R(emu);
 2086         else
 2087                 x86emuOp16_mov_word_RM_R(emu);
 2088 }
 2089 
 2090 /*
 2091  * REMARKS:
 2092  * Handles opcode 0x8a
 2093  */
 2094 static void
 2095 x86emuOp_mov_byte_R_RM(struct x86emu *emu)
 2096 {
 2097         uint8_t *destreg;
 2098 
 2099         fetch_decode_modrm(emu);
 2100         destreg = decode_rh_byte_register(emu);
 2101         *destreg = decode_and_fetch_byte(emu);
 2102 }
 2103 
 2104 /*
 2105  * REMARKS:
 2106  * Handles opcode 0x8b
 2107  */
 2108 static void
 2109 x86emuOp_mov_word_R_RM(struct x86emu *emu)
 2110 {
 2111         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2112                 uint32_t *destreg;
 2113 
 2114                 fetch_decode_modrm(emu);
 2115                 destreg = decode_rh_long_register(emu);
 2116                 *destreg = decode_and_fetch_long(emu);
 2117         } else {
 2118                 uint16_t *destreg;
 2119 
 2120                 fetch_decode_modrm(emu);
 2121                 destreg = decode_rh_word_register(emu);
 2122                 *destreg = decode_and_fetch_word(emu);
 2123         }
 2124 }
 2125 
 2126 /*
 2127  * REMARKS:
 2128  * Handles opcode 0x8c
 2129  */
 2130 static void
 2131 x86emuOp_mov_word_RM_SR(struct x86emu *emu)
 2132 {
 2133         uint16_t *destreg, srcval;
 2134         uint32_t destoffset;
 2135 
 2136         fetch_decode_modrm(emu);
 2137         srcval = *decode_rh_seg_register(emu);
 2138         if (emu->cur_mod != 3) {
 2139                 destoffset = decode_rl_address(emu);
 2140                 store_data_word(emu, destoffset, srcval);
 2141         } else {
 2142                 destreg = decode_rl_word_register(emu);
 2143                 *destreg = srcval;
 2144         }
 2145 }
 2146 
 2147 /*
 2148  * REMARKS:
 2149  * Handles opcode 0x8d
 2150  */
 2151 static void
 2152 x86emuOp_lea_word_R_M(struct x86emu *emu)
 2153 {
 2154         uint32_t destoffset;
 2155 
 2156         fetch_decode_modrm(emu);
 2157         if (emu->cur_mod == 3)
 2158                 x86emu_halt_sys(emu);
 2159 
 2160         destoffset = decode_rl_address(emu);
 2161         if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
 2162                 uint32_t *srcreg;
 2163 
 2164                 srcreg = decode_rh_long_register(emu);
 2165                 *srcreg = (uint32_t) destoffset;
 2166         } else {
 2167                 uint16_t *srcreg;
 2168 
 2169                 srcreg = decode_rh_word_register(emu);
 2170                 *srcreg = (uint16_t) destoffset;
 2171         }
 2172 }
 2173 
 2174 /*
 2175  * REMARKS:
 2176  * Handles opcode 0x8e
 2177  */
 2178 static void
 2179 x86emuOp_mov_word_SR_RM(struct x86emu *emu)
 2180 {
 2181         uint16_t *destreg;
 2182 
 2183         fetch_decode_modrm(emu);
 2184         destreg = decode_rh_seg_register(emu);
 2185         *destreg = decode_and_fetch_word(emu);
 2186         /*
 2187          * Clean up, and reset all the R_xSP pointers to the correct
 2188          * locations.  This is about 3x too much overhead (doing all the
 2189          * segreg ptrs when only one is needed, but this instruction
 2190          * *cannot* be that common, and this isn't too much work anyway.
 2191          */
 2192 }
 2193 
 2194 /*
 2195  * REMARKS:
 2196  * Handles opcode 0x8f
 2197  */
 2198 static void
 2199 x86emuOp32_pop_RM(struct x86emu *emu)
 2200 {
 2201         uint32_t destoffset;
 2202         uint32_t destval, *destreg;
 2203 
 2204         fetch_decode_modrm(emu);
 2205         if (emu->cur_mod != 3) {
 2206                 destoffset = decode_rl_address(emu);
 2207                 destval = pop_long(emu);
 2208                 store_data_long(emu, destoffset, destval);
 2209         } else {
 2210                 destreg = decode_rl_long_register(emu);
 2211                 *destreg = pop_long(emu);
 2212         }
 2213 }
 2214 
 2215 static void
 2216 x86emuOp16_pop_RM(struct x86emu *emu)
 2217 {
 2218         uint32_t destoffset;
 2219         uint16_t destval, *destreg;
 2220 
 2221         fetch_decode_modrm(emu);
 2222         if (emu->cur_mod != 3) {
 2223                 destoffset = decode_rl_address(emu);
 2224                 destval = pop_word(emu);
 2225                 store_data_word(emu, destoffset, destval);
 2226         } else {
 2227                 destreg = decode_rl_word_register(emu);
 2228                 *destreg = pop_word(emu);
 2229         }
 2230 }
 2231 
 2232 static void
 2233 x86emuOp_pop_RM(struct x86emu *emu)
 2234 {
 2235         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2236                 x86emuOp32_pop_RM(emu);
 2237         else
 2238                 x86emuOp16_pop_RM(emu);
 2239 }
 2240 
 2241 /*
 2242  * REMARKS:
 2243  * Handles opcode 0x91
 2244  */
 2245 static void
 2246 x86emuOp_xchg_word_AX_CX(struct x86emu *emu)
 2247 {
 2248         uint32_t tmp;
 2249 
 2250         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2251                 tmp = emu->x86.R_EAX;
 2252                 emu->x86.R_EAX = emu->x86.R_ECX;
 2253                 emu->x86.R_ECX = tmp;
 2254         } else {
 2255                 tmp = emu->x86.R_AX;
 2256                 emu->x86.R_AX = emu->x86.R_CX;
 2257                 emu->x86.R_CX = (uint16_t) tmp;
 2258         }
 2259 }
 2260 
 2261 /*
 2262  * REMARKS:
 2263  * Handles opcode 0x92
 2264  */
 2265 static void
 2266 x86emuOp_xchg_word_AX_DX(struct x86emu *emu)
 2267 {
 2268         uint32_t tmp;
 2269 
 2270         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2271                 tmp = emu->x86.R_EAX;
 2272                 emu->x86.R_EAX = emu->x86.R_EDX;
 2273                 emu->x86.R_EDX = tmp;
 2274         } else {
 2275                 tmp = emu->x86.R_AX;
 2276                 emu->x86.R_AX = emu->x86.R_DX;
 2277                 emu->x86.R_DX = (uint16_t) tmp;
 2278         }
 2279 }
 2280 
 2281 /*
 2282  * REMARKS:
 2283  * Handles opcode 0x93
 2284  */
 2285 static void
 2286 x86emuOp_xchg_word_AX_BX(struct x86emu *emu)
 2287 {
 2288         uint32_t tmp;
 2289 
 2290         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2291                 tmp = emu->x86.R_EAX;
 2292                 emu->x86.R_EAX = emu->x86.R_EBX;
 2293                 emu->x86.R_EBX = tmp;
 2294         } else {
 2295                 tmp = emu->x86.R_AX;
 2296                 emu->x86.R_AX = emu->x86.R_BX;
 2297                 emu->x86.R_BX = (uint16_t) tmp;
 2298         }
 2299 }
 2300 
 2301 /*
 2302  * REMARKS:
 2303  * Handles opcode 0x94
 2304  */
 2305 static void
 2306 x86emuOp_xchg_word_AX_SP(struct x86emu *emu)
 2307 {
 2308         uint32_t tmp;
 2309 
 2310         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2311                 tmp = emu->x86.R_EAX;
 2312                 emu->x86.R_EAX = emu->x86.R_ESP;
 2313                 emu->x86.R_ESP = tmp;
 2314         } else {
 2315                 tmp = emu->x86.R_AX;
 2316                 emu->x86.R_AX = emu->x86.R_SP;
 2317                 emu->x86.R_SP = (uint16_t) tmp;
 2318         }
 2319 }
 2320 
 2321 /*
 2322  * REMARKS:
 2323  * Handles opcode 0x95
 2324  */
 2325 static void
 2326 x86emuOp_xchg_word_AX_BP(struct x86emu *emu)
 2327 {
 2328         uint32_t tmp;
 2329 
 2330         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2331                 tmp = emu->x86.R_EAX;
 2332                 emu->x86.R_EAX = emu->x86.R_EBP;
 2333                 emu->x86.R_EBP = tmp;
 2334         } else {
 2335                 tmp = emu->x86.R_AX;
 2336                 emu->x86.R_AX = emu->x86.R_BP;
 2337                 emu->x86.R_BP = (uint16_t) tmp;
 2338         }
 2339 }
 2340 
 2341 /*
 2342  * REMARKS:
 2343  * Handles opcode 0x96
 2344  */
 2345 static void
 2346 x86emuOp_xchg_word_AX_SI(struct x86emu *emu)
 2347 {
 2348         uint32_t tmp;
 2349 
 2350         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2351                 tmp = emu->x86.R_EAX;
 2352                 emu->x86.R_EAX = emu->x86.R_ESI;
 2353                 emu->x86.R_ESI = tmp;
 2354         } else {
 2355                 tmp = emu->x86.R_AX;
 2356                 emu->x86.R_AX = emu->x86.R_SI;
 2357                 emu->x86.R_SI = (uint16_t) tmp;
 2358         }
 2359 }
 2360 
 2361 /*
 2362  * REMARKS:
 2363  * Handles opcode 0x97
 2364  */
 2365 static void
 2366 x86emuOp_xchg_word_AX_DI(struct x86emu *emu)
 2367 {
 2368         uint32_t tmp;
 2369 
 2370         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2371                 tmp = emu->x86.R_EAX;
 2372                 emu->x86.R_EAX = emu->x86.R_EDI;
 2373                 emu->x86.R_EDI = tmp;
 2374         } else {
 2375                 tmp = emu->x86.R_AX;
 2376                 emu->x86.R_AX = emu->x86.R_DI;
 2377                 emu->x86.R_DI = (uint16_t) tmp;
 2378         }
 2379 }
 2380 
 2381 /*
 2382  * REMARKS:
 2383  * Handles opcode 0x98
 2384  */
 2385 static void
 2386 x86emuOp_cbw(struct x86emu *emu)
 2387 {
 2388         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2389                 if (emu->x86.R_AX & 0x8000) {
 2390                         emu->x86.R_EAX |= 0xffff0000;
 2391                 } else {
 2392                         emu->x86.R_EAX &= 0x0000ffff;
 2393                 }
 2394         } else {
 2395                 if (emu->x86.R_AL & 0x80) {
 2396                         emu->x86.R_AH = 0xff;
 2397                 } else {
 2398                         emu->x86.R_AH = 0x0;
 2399                 }
 2400         }
 2401 }
 2402 
 2403 /*
 2404  * REMARKS:
 2405  * Handles opcode 0x99
 2406  */
 2407 static void
 2408 x86emuOp_cwd(struct x86emu *emu)
 2409 {
 2410         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2411                 if (emu->x86.R_EAX & 0x80000000) {
 2412                         emu->x86.R_EDX = 0xffffffff;
 2413                 } else {
 2414                         emu->x86.R_EDX = 0x0;
 2415                 }
 2416         } else {
 2417                 if (emu->x86.R_AX & 0x8000) {
 2418                         emu->x86.R_DX = 0xffff;
 2419                 } else {
 2420                         emu->x86.R_DX = 0x0;
 2421                 }
 2422         }
 2423 }
 2424 
 2425 /*
 2426  * REMARKS:
 2427  * Handles opcode 0x9a
 2428  */
 2429 static void
 2430 x86emuOp_call_far_IMM(struct x86emu *emu)
 2431 {
 2432         uint16_t farseg, faroff;
 2433 
 2434         faroff = fetch_word_imm(emu);
 2435         farseg = fetch_word_imm(emu);
 2436         /* XXX
 2437          * 
 2438          * Hooked interrupt vectors calling into our "BIOS" will cause problems
 2439          * unless all intersegment stuff is checked for BIOS access.  Check
 2440          * needed here.  For moment, let it alone. */
 2441         push_word(emu, emu->x86.R_CS);
 2442         emu->x86.R_CS = farseg;
 2443         push_word(emu, emu->x86.R_IP);
 2444         emu->x86.R_IP = faroff;
 2445 }
 2446 
 2447 /*
 2448  * REMARKS:
 2449  * Handles opcode 0x9c
 2450  */
 2451 static void
 2452 x86emuOp_pushf_word(struct x86emu *emu)
 2453 {
 2454         uint32_t flags;
 2455 
 2456         /* clear out *all* bits not representing flags, and turn on real bits */
 2457         flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
 2458         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2459                 push_long(emu, flags);
 2460         } else {
 2461                 push_word(emu, (uint16_t) flags);
 2462         }
 2463 }
 2464 
 2465 /*
 2466  * REMARKS:
 2467  * Handles opcode 0x9d
 2468  */
 2469 static void
 2470 x86emuOp_popf_word(struct x86emu *emu)
 2471 {
 2472         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2473                 emu->x86.R_EFLG = pop_long(emu);
 2474         } else {
 2475                 emu->x86.R_FLG = pop_word(emu);
 2476         }
 2477 }
 2478 
 2479 /*
 2480  * REMARKS:
 2481  * Handles opcode 0x9e
 2482  */
 2483 static void
 2484 x86emuOp_sahf(struct x86emu *emu)
 2485 {
 2486         /* clear the lower bits of the flag register */
 2487         emu->x86.R_FLG &= 0xffffff00;
 2488         /* or in the AH register into the flags register */
 2489         emu->x86.R_FLG |= emu->x86.R_AH;
 2490 }
 2491 
 2492 /*
 2493  * REMARKS:
 2494  * Handles opcode 0x9f
 2495  */
 2496 static void
 2497 x86emuOp_lahf(struct x86emu *emu)
 2498 {
 2499         emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
 2500         /* undocumented TC++ behavior??? Nope.  It's documented, but you have
 2501          * too look real hard to notice it. */
 2502         emu->x86.R_AH |= 0x2;
 2503 }
 2504 
 2505 /*
 2506  * REMARKS:
 2507  * Handles opcode 0xa0
 2508  */
 2509 static void
 2510 x86emuOp_mov_AL_M_IMM(struct x86emu *emu)
 2511 {
 2512         uint16_t offset;
 2513 
 2514         offset = fetch_word_imm(emu);
 2515         emu->x86.R_AL = fetch_data_byte(emu, offset);
 2516 }
 2517 
 2518 /*
 2519  * REMARKS:
 2520  * Handles opcode 0xa1
 2521  */
 2522 static void
 2523 x86emuOp_mov_AX_M_IMM(struct x86emu *emu)
 2524 {
 2525         uint16_t offset;
 2526 
 2527         offset = fetch_word_imm(emu);
 2528         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2529                 emu->x86.R_EAX = fetch_data_long(emu, offset);
 2530         } else {
 2531                 emu->x86.R_AX = fetch_data_word(emu, offset);
 2532         }
 2533 }
 2534 
 2535 /*
 2536  * REMARKS:
 2537  * Handles opcode 0xa2
 2538  */
 2539 static void
 2540 x86emuOp_mov_M_AL_IMM(struct x86emu *emu)
 2541 {
 2542         uint16_t offset;
 2543 
 2544         offset = fetch_word_imm(emu);
 2545         store_data_byte(emu, offset, emu->x86.R_AL);
 2546 }
 2547 
 2548 /*
 2549  * REMARKS:
 2550  * Handles opcode 0xa3
 2551  */
 2552 static void
 2553 x86emuOp_mov_M_AX_IMM(struct x86emu *emu)
 2554 {
 2555         uint16_t offset;
 2556 
 2557         offset = fetch_word_imm(emu);
 2558         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2559                 store_data_long(emu, offset, emu->x86.R_EAX);
 2560         } else {
 2561                 store_data_word(emu, offset, emu->x86.R_AX);
 2562         }
 2563 }
 2564 
 2565 /*
 2566  * REMARKS:
 2567  * Handles opcode 0xa4
 2568  */
 2569 static void
 2570 x86emuOp_movs_byte(struct x86emu *emu)
 2571 {
 2572         uint8_t val;
 2573         uint32_t count;
 2574         int inc;
 2575 
 2576         if (ACCESS_FLAG(F_DF))  /* down */
 2577                 inc = -1;
 2578         else
 2579                 inc = 1;
 2580         count = 1;
 2581         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 2582                 /* dont care whether REPE or REPNE */
 2583                 /* move them until CX is ZERO. */
 2584                 count = emu->x86.R_CX;
 2585                 emu->x86.R_CX = 0;
 2586                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 2587         }
 2588         while (count--) {
 2589                 val = fetch_data_byte(emu, emu->x86.R_SI);
 2590                 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
 2591                 emu->x86.R_SI += inc;
 2592                 emu->x86.R_DI += inc;
 2593         }
 2594 }
 2595 
 2596 /*
 2597  * REMARKS:
 2598  * Handles opcode 0xa5
 2599  */
 2600 static void
 2601 x86emuOp_movs_word(struct x86emu *emu)
 2602 {
 2603         uint32_t val;
 2604         int inc;
 2605         uint32_t count;
 2606 
 2607         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2608                 inc = 4;
 2609         else
 2610                 inc = 2;
 2611 
 2612         if (ACCESS_FLAG(F_DF))  /* down */
 2613                 inc = -inc;
 2614 
 2615         count = 1;
 2616         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 2617                 /* dont care whether REPE or REPNE */
 2618                 /* move them until CX is ZERO. */
 2619                 count = emu->x86.R_CX;
 2620                 emu->x86.R_CX = 0;
 2621                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 2622         }
 2623         while (count--) {
 2624                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2625                         val = fetch_data_long(emu, emu->x86.R_SI);
 2626                         store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
 2627                 } else {
 2628                         val = fetch_data_word(emu, emu->x86.R_SI);
 2629                         store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
 2630                             (uint16_t) val);
 2631                 }
 2632                 emu->x86.R_SI += inc;
 2633                 emu->x86.R_DI += inc;
 2634         }
 2635 }
 2636 
 2637 /*
 2638  * REMARKS:
 2639  * Handles opcode 0xa6
 2640  */
 2641 static void
 2642 x86emuOp_cmps_byte(struct x86emu *emu)
 2643 {
 2644         int8_t val1, val2;
 2645         int inc;
 2646 
 2647         if (ACCESS_FLAG(F_DF))  /* down */
 2648                 inc = -1;
 2649         else
 2650                 inc = 1;
 2651 
 2652         if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
 2653                 /* REPE  */
 2654                 /* move them until CX is ZERO. */
 2655                 while (emu->x86.R_CX != 0) {
 2656                         val1 = fetch_data_byte(emu, emu->x86.R_SI);
 2657                         val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
 2658                         cmp_byte(emu, val1, val2);
 2659                         emu->x86.R_CX -= 1;
 2660                         emu->x86.R_SI += inc;
 2661                         emu->x86.R_DI += inc;
 2662                         if (ACCESS_FLAG(F_ZF) == 0)
 2663                                 break;
 2664                 }
 2665                 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
 2666         } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
 2667                 /* REPNE  */
 2668                 /* move them until CX is ZERO. */
 2669                 while (emu->x86.R_CX != 0) {
 2670                         val1 = fetch_data_byte(emu, emu->x86.R_SI);
 2671                         val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
 2672                         cmp_byte(emu, val1, val2);
 2673                         emu->x86.R_CX -= 1;
 2674                         emu->x86.R_SI += inc;
 2675                         emu->x86.R_DI += inc;
 2676                         if (ACCESS_FLAG(F_ZF))
 2677                                 break;  /* zero flag set means equal */
 2678                 }
 2679                 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
 2680         } else {
 2681                 val1 = fetch_data_byte(emu, emu->x86.R_SI);
 2682                 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
 2683                 cmp_byte(emu, val1, val2);
 2684                 emu->x86.R_SI += inc;
 2685                 emu->x86.R_DI += inc;
 2686         }
 2687 }
 2688 
 2689 /*
 2690  * REMARKS:
 2691  * Handles opcode 0xa7
 2692  */
 2693 static void
 2694 x86emuOp_cmps_word(struct x86emu *emu)
 2695 {
 2696         uint32_t val1, val2;
 2697         int inc;
 2698 
 2699         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2700                 if (ACCESS_FLAG(F_DF))  /* down */
 2701                         inc = -4;
 2702                 else
 2703                         inc = 4;
 2704         } else {
 2705                 if (ACCESS_FLAG(F_DF))  /* down */
 2706                         inc = -2;
 2707                 else
 2708                         inc = 2;
 2709         }
 2710         if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
 2711                 /* REPE  */
 2712                 /* move them until CX is ZERO. */
 2713                 while (emu->x86.R_CX != 0) {
 2714                         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2715                                 val1 = fetch_data_long(emu, emu->x86.R_SI);
 2716                                 val2 = fetch_long(emu, emu->x86.R_ES,
 2717                                     emu->x86.R_DI);
 2718                                 cmp_long(emu, val1, val2);
 2719                         } else {
 2720                                 val1 = fetch_data_word(emu, emu->x86.R_SI);
 2721                                 val2 = fetch_word(emu, emu->x86.R_ES,
 2722                                     emu->x86.R_DI);
 2723                                 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
 2724                         }
 2725                         emu->x86.R_CX -= 1;
 2726                         emu->x86.R_SI += inc;
 2727                         emu->x86.R_DI += inc;
 2728                         if (ACCESS_FLAG(F_ZF) == 0)
 2729                                 break;
 2730                 }
 2731                 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
 2732         } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
 2733                 /* REPNE  */
 2734                 /* move them until CX is ZERO. */
 2735                 while (emu->x86.R_CX != 0) {
 2736                         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2737                                 val1 = fetch_data_long(emu, emu->x86.R_SI);
 2738                                 val2 = fetch_long(emu, emu->x86.R_ES,
 2739                                     emu->x86.R_DI);
 2740                                 cmp_long(emu, val1, val2);
 2741                         } else {
 2742                                 val1 = fetch_data_word(emu, emu->x86.R_SI);
 2743                                 val2 = fetch_word(emu, emu->x86.R_ES,
 2744                                     emu->x86.R_DI);
 2745                                 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
 2746                         }
 2747                         emu->x86.R_CX -= 1;
 2748                         emu->x86.R_SI += inc;
 2749                         emu->x86.R_DI += inc;
 2750                         if (ACCESS_FLAG(F_ZF))
 2751                                 break;  /* zero flag set means equal */
 2752                 }
 2753                 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
 2754         } else {
 2755                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2756                         val1 = fetch_data_long(emu, emu->x86.R_SI);
 2757                         val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
 2758                         cmp_long(emu, val1, val2);
 2759                 } else {
 2760                         val1 = fetch_data_word(emu, emu->x86.R_SI);
 2761                         val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
 2762                         cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
 2763                 }
 2764                 emu->x86.R_SI += inc;
 2765                 emu->x86.R_DI += inc;
 2766         }
 2767 }
 2768 
 2769 /*
 2770  * REMARKS:
 2771  * Handles opcode 0xa9
 2772  */
 2773 static void
 2774 x86emuOp_test_AX_IMM(struct x86emu *emu)
 2775 {
 2776         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2777                 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
 2778         } else {
 2779                 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
 2780         }
 2781 }
 2782 
 2783 /*
 2784  * REMARKS:
 2785  * Handles opcode 0xaa
 2786  */
 2787 static void
 2788 x86emuOp_stos_byte(struct x86emu *emu)
 2789 {
 2790         int inc;
 2791 
 2792         if (ACCESS_FLAG(F_DF))  /* down */
 2793                 inc = -1;
 2794         else
 2795                 inc = 1;
 2796         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 2797                 /* dont care whether REPE or REPNE */
 2798                 /* move them until CX is ZERO. */
 2799                 while (emu->x86.R_CX != 0) {
 2800                         store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
 2801                             emu->x86.R_AL);
 2802                         emu->x86.R_CX -= 1;
 2803                         emu->x86.R_DI += inc;
 2804                 }
 2805                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 2806         } else {
 2807                 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
 2808                 emu->x86.R_DI += inc;
 2809         }
 2810 }
 2811 
 2812 /*
 2813  * REMARKS:
 2814  * Handles opcode 0xab
 2815  */
 2816 static void
 2817 x86emuOp_stos_word(struct x86emu *emu)
 2818 {
 2819         int inc;
 2820         uint32_t count;
 2821 
 2822         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2823                 inc = 4;
 2824         else
 2825                 inc = 2;
 2826         
 2827         if (ACCESS_FLAG(F_DF))  /* down */
 2828                 inc = -inc;
 2829 
 2830         count = 1;
 2831         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 2832                 /* dont care whether REPE or REPNE */
 2833                 /* move them until CX is ZERO. */
 2834                 count = emu->x86.R_CX;
 2835                 emu->x86.R_CX = 0;
 2836                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 2837         }
 2838         while (count--) {
 2839                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2840                         store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
 2841                             emu->x86.R_EAX);
 2842                 } else {
 2843                         store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
 2844                             emu->x86.R_AX);
 2845                 }
 2846                 emu->x86.R_DI += inc;
 2847         }
 2848 }
 2849 
 2850 /*
 2851  * REMARKS:
 2852  * Handles opcode 0xac
 2853  */
 2854 static void
 2855 x86emuOp_lods_byte(struct x86emu *emu)
 2856 {
 2857         int inc;
 2858 
 2859         if (ACCESS_FLAG(F_DF))  /* down */
 2860                 inc = -1;
 2861         else
 2862                 inc = 1;
 2863         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 2864                 /* dont care whether REPE or REPNE */
 2865                 /* move them until CX is ZERO. */
 2866                 while (emu->x86.R_CX != 0) {
 2867                         emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
 2868                         emu->x86.R_CX -= 1;
 2869                         emu->x86.R_SI += inc;
 2870                 }
 2871                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 2872         } else {
 2873                 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
 2874                 emu->x86.R_SI += inc;
 2875         }
 2876 }
 2877 
 2878 /*
 2879  * REMARKS:
 2880  * Handles opcode 0xad
 2881  */
 2882 static void
 2883 x86emuOp_lods_word(struct x86emu *emu)
 2884 {
 2885         int inc;
 2886         uint32_t count;
 2887 
 2888         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2889                 inc = 4;
 2890         else
 2891                 inc = 2;
 2892 
 2893         if (ACCESS_FLAG(F_DF))  /* down */
 2894                 inc = -inc;
 2895 
 2896         count = 1;
 2897         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 2898                 /* dont care whether REPE or REPNE */
 2899                 /* move them until CX is ZERO. */
 2900                 count = emu->x86.R_CX;
 2901                 emu->x86.R_CX = 0;
 2902                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 2903         }
 2904         while (count--) {
 2905                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2906                         emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
 2907                 } else {
 2908                         emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
 2909                 }
 2910                 emu->x86.R_SI += inc;
 2911         }
 2912 }
 2913 
 2914 /*
 2915  * REMARKS:
 2916  * Handles opcode 0xae
 2917  */
 2918 static void
 2919 x86emuOp_scas_byte(struct x86emu *emu)
 2920 {
 2921         int8_t val2;
 2922         int inc;
 2923 
 2924         if (ACCESS_FLAG(F_DF))  /* down */
 2925                 inc = -1;
 2926         else
 2927                 inc = 1;
 2928         if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
 2929                 /* REPE  */
 2930                 /* move them until CX is ZERO. */
 2931                 while (emu->x86.R_CX != 0) {
 2932                         val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
 2933                         cmp_byte(emu, emu->x86.R_AL, val2);
 2934                         emu->x86.R_CX -= 1;
 2935                         emu->x86.R_DI += inc;
 2936                         if (ACCESS_FLAG(F_ZF) == 0)
 2937                                 break;
 2938                 }
 2939                 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
 2940         } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
 2941                 /* REPNE  */
 2942                 /* move them until CX is ZERO. */
 2943                 while (emu->x86.R_CX != 0) {
 2944                         val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
 2945                         cmp_byte(emu, emu->x86.R_AL, val2);
 2946                         emu->x86.R_CX -= 1;
 2947                         emu->x86.R_DI += inc;
 2948                         if (ACCESS_FLAG(F_ZF))
 2949                                 break;  /* zero flag set means equal */
 2950                 }
 2951                 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
 2952         } else {
 2953                 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
 2954                 cmp_byte(emu, emu->x86.R_AL, val2);
 2955                 emu->x86.R_DI += inc;
 2956         }
 2957 }
 2958 
 2959 /*
 2960  * REMARKS:
 2961  * Handles opcode 0xaf
 2962  */
 2963 static void
 2964 x86emuOp_scas_word(struct x86emu *emu)
 2965 {
 2966         int inc;
 2967         uint32_t val;
 2968 
 2969         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 2970                 inc = 4;
 2971         else
 2972                 inc = 2;
 2973 
 2974         if (ACCESS_FLAG(F_DF))  /* down */
 2975                 inc = -inc;
 2976 
 2977         if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
 2978                 /* REPE  */
 2979                 /* move them until CX is ZERO. */
 2980                 while (emu->x86.R_CX != 0) {
 2981                         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 2982                                 val = fetch_long(emu, emu->x86.R_ES,
 2983                                     emu->x86.R_DI);
 2984                                 cmp_long(emu, emu->x86.R_EAX, val);
 2985                         } else {
 2986                                 val = fetch_word(emu, emu->x86.R_ES,
 2987                                     emu->x86.R_DI);
 2988                                 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
 2989                         }
 2990                         emu->x86.R_CX -= 1;
 2991                         emu->x86.R_DI += inc;
 2992                         if (ACCESS_FLAG(F_ZF) == 0)
 2993                                 break;
 2994                 }
 2995                 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
 2996         } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
 2997                 /* REPNE  */
 2998                 /* move them until CX is ZERO. */
 2999                 while (emu->x86.R_CX != 0) {
 3000                         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3001                                 val = fetch_long(emu, emu->x86.R_ES,
 3002                                     emu->x86.R_DI);
 3003                                 cmp_long(emu, emu->x86.R_EAX, val);
 3004                         } else {
 3005                                 val = fetch_word(emu, emu->x86.R_ES,
 3006                                     emu->x86.R_DI);
 3007                                 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
 3008                         }
 3009                         emu->x86.R_CX -= 1;
 3010                         emu->x86.R_DI += inc;
 3011                         if (ACCESS_FLAG(F_ZF))
 3012                                 break;  /* zero flag set means equal */
 3013                 }
 3014                 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
 3015         } else {
 3016                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3017                         val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
 3018                         cmp_long(emu, emu->x86.R_EAX, val);
 3019                 } else {
 3020                         val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
 3021                         cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
 3022                 }
 3023                 emu->x86.R_DI += inc;
 3024         }
 3025 }
 3026 
 3027 /*
 3028  * REMARKS:
 3029  * Handles opcode 0xb8
 3030  */
 3031 static void
 3032 x86emuOp_mov_word_AX_IMM(struct x86emu *emu)
 3033 {
 3034         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3035                 emu->x86.R_EAX = fetch_long_imm(emu);
 3036         else
 3037                 emu->x86.R_AX = fetch_word_imm(emu);
 3038 }
 3039 
 3040 /*
 3041  * REMARKS:
 3042  * Handles opcode 0xb9
 3043  */
 3044 static void
 3045 x86emuOp_mov_word_CX_IMM(struct x86emu *emu)
 3046 {
 3047         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3048                 emu->x86.R_ECX = fetch_long_imm(emu);
 3049         else
 3050                 emu->x86.R_CX = fetch_word_imm(emu);
 3051 }
 3052 
 3053 /*
 3054  * REMARKS:
 3055  * Handles opcode 0xba
 3056  */
 3057 static void
 3058 x86emuOp_mov_word_DX_IMM(struct x86emu *emu)
 3059 {
 3060         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3061                 emu->x86.R_EDX = fetch_long_imm(emu);
 3062         else
 3063                 emu->x86.R_DX = fetch_word_imm(emu);
 3064 }
 3065 
 3066 /*
 3067  * REMARKS:
 3068  * Handles opcode 0xbb
 3069  */
 3070 static void
 3071 x86emuOp_mov_word_BX_IMM(struct x86emu *emu)
 3072 {
 3073         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3074                 emu->x86.R_EBX = fetch_long_imm(emu);
 3075         else
 3076                 emu->x86.R_BX = fetch_word_imm(emu);
 3077 }
 3078 
 3079 /*
 3080  * REMARKS:
 3081  * Handles opcode 0xbc
 3082  */
 3083 static void
 3084 x86emuOp_mov_word_SP_IMM(struct x86emu *emu)
 3085 {
 3086         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3087                 emu->x86.R_ESP = fetch_long_imm(emu);
 3088         else
 3089                 emu->x86.R_SP = fetch_word_imm(emu);
 3090 }
 3091 
 3092 /*
 3093  * REMARKS:
 3094  * Handles opcode 0xbd
 3095  */
 3096 static void
 3097 x86emuOp_mov_word_BP_IMM(struct x86emu *emu)
 3098 {
 3099         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3100                 emu->x86.R_EBP = fetch_long_imm(emu);
 3101         else
 3102                 emu->x86.R_BP = fetch_word_imm(emu);
 3103 }
 3104 
 3105 /*
 3106  * REMARKS:
 3107  * Handles opcode 0xbe
 3108  */
 3109 static void
 3110 x86emuOp_mov_word_SI_IMM(struct x86emu *emu)
 3111 {
 3112         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3113                 emu->x86.R_ESI = fetch_long_imm(emu);
 3114         else
 3115                 emu->x86.R_SI = fetch_word_imm(emu);
 3116 }
 3117 
 3118 /*
 3119  * REMARKS:
 3120  * Handles opcode 0xbf
 3121  */
 3122 static void
 3123 x86emuOp_mov_word_DI_IMM(struct x86emu *emu)
 3124 {
 3125         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3126                 emu->x86.R_EDI = fetch_long_imm(emu);
 3127         else
 3128                 emu->x86.R_DI = fetch_word_imm(emu);
 3129 }
 3130 /* used by opcodes c0, d0, and d2. */
 3131 static
 3132 uint8_t(* const opcD0_byte_operation[])
 3133     (struct x86emu *, uint8_t d, uint8_t s) =
 3134 {
 3135         rol_byte,
 3136         ror_byte,
 3137         rcl_byte,
 3138         rcr_byte,
 3139         shl_byte,
 3140         shr_byte,
 3141         shl_byte,               /* sal_byte === shl_byte  by definition */
 3142         sar_byte,
 3143 };
 3144 
 3145 /*
 3146  * REMARKS:
 3147  * Handles opcode 0xc0
 3148  */
 3149 static void
 3150 x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
 3151 {
 3152         uint8_t destval, amt;
 3153 
 3154         /*
 3155          * Yet another weirdo special case instruction format.  Part of
 3156          * the opcode held below in "RH".  Doubly nested case would
 3157          * result, except that the decoded instruction
 3158          */
 3159         fetch_decode_modrm(emu);
 3160         /* know operation, decode the mod byte to find the addressing mode. */
 3161         destval = decode_and_fetch_byte_imm8(emu, &amt);
 3162         destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
 3163         write_back_byte(emu, destval);
 3164 }
 3165 /* used by opcodes c1, d1, and d3. */
 3166 static
 3167 uint16_t(* const opcD1_word_operation[])
 3168     (struct x86emu *, uint16_t s, uint8_t d) =
 3169 {
 3170         rol_word,
 3171         ror_word,
 3172         rcl_word,
 3173         rcr_word,
 3174         shl_word,
 3175         shr_word,
 3176         shl_word,               /* sal_byte === shl_byte  by definition */
 3177         sar_word,
 3178 };
 3179 /* used by opcodes c1, d1, and d3. */
 3180 static
 3181 uint32_t(* const opcD1_long_operation[])
 3182     (struct x86emu *, uint32_t s, uint8_t d) =
 3183 {
 3184         rol_long,
 3185         ror_long,
 3186         rcl_long,
 3187         rcr_long,
 3188         shl_long,
 3189         shr_long,
 3190         shl_long,               /* sal_byte === shl_byte  by definition */
 3191         sar_long,
 3192 };
 3193 
 3194 /*
 3195  * REMARKS:
 3196  * Handles opcode 0xc1
 3197  */
 3198 static void
 3199 x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
 3200 {
 3201         uint8_t amt;
 3202 
 3203         /*
 3204          * Yet another weirdo special case instruction format.  Part of
 3205          * the opcode held below in "RH".  Doubly nested case would
 3206          * result, except that the decoded instruction
 3207          */
 3208         fetch_decode_modrm(emu);
 3209         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3210                 uint32_t destval;
 3211 
 3212                 destval = decode_and_fetch_long_imm8(emu, &amt);
 3213                 destval = (*opcD1_long_operation[emu->cur_rh])
 3214                     (emu, destval, amt);
 3215                 write_back_long(emu, destval);
 3216         } else {
 3217                 uint16_t destval;
 3218 
 3219                 destval = decode_and_fetch_word_imm8(emu, &amt);
 3220                 destval = (*opcD1_word_operation[emu->cur_rh])
 3221                     (emu, destval, amt);
 3222                 write_back_word(emu, destval);
 3223         }
 3224 }
 3225 
 3226 /*
 3227  * REMARKS:
 3228  * Handles opcode 0xc2
 3229  */
 3230 static void
 3231 x86emuOp_ret_near_IMM(struct x86emu *emu)
 3232 {
 3233         uint16_t imm;
 3234 
 3235         imm = fetch_word_imm(emu);
 3236         emu->x86.R_IP = pop_word(emu);
 3237         emu->x86.R_SP += imm;
 3238 }
 3239 
 3240 /*
 3241  * REMARKS:
 3242  * Handles opcode 0xc6
 3243  */
 3244 static void
 3245 x86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
 3246 {
 3247         uint8_t *destreg;
 3248         uint32_t destoffset;
 3249         uint8_t imm;
 3250 
 3251         fetch_decode_modrm(emu);
 3252         if (emu->cur_rh != 0)
 3253                 x86emu_halt_sys(emu);
 3254         if (emu->cur_mod != 3) {
 3255                 destoffset = decode_rl_address(emu);
 3256                 imm = fetch_byte_imm(emu);
 3257                 store_data_byte(emu, destoffset, imm);
 3258         } else {
 3259                 destreg = decode_rl_byte_register(emu);
 3260                 imm = fetch_byte_imm(emu);
 3261                 *destreg = imm;
 3262         }
 3263 }
 3264 
 3265 /*
 3266  * REMARKS:
 3267  * Handles opcode 0xc7
 3268  */
 3269 static void
 3270 x86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
 3271 {
 3272         uint32_t destoffset;
 3273         uint32_t imm, *destreg;
 3274 
 3275         fetch_decode_modrm(emu);
 3276         if (emu->cur_rh != 0)
 3277                 x86emu_halt_sys(emu);
 3278 
 3279         if (emu->cur_mod != 3) {
 3280                 destoffset = decode_rl_address(emu);
 3281                 imm = fetch_long_imm(emu);
 3282                 store_data_long(emu, destoffset, imm);
 3283         } else {
 3284                 destreg = decode_rl_long_register(emu);
 3285                 imm = fetch_long_imm(emu);
 3286                 *destreg = imm;
 3287         }
 3288 }
 3289 
 3290 static void
 3291 x86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
 3292 {
 3293         uint32_t destoffset;
 3294         uint16_t imm, *destreg;
 3295 
 3296         fetch_decode_modrm(emu);
 3297         if (emu->cur_rh != 0)
 3298                 x86emu_halt_sys(emu);
 3299 
 3300         if (emu->cur_mod != 3) {
 3301                 destoffset = decode_rl_address(emu);
 3302                 imm = fetch_word_imm(emu);
 3303                 store_data_word(emu, destoffset, imm);
 3304         } else {
 3305                 destreg = decode_rl_word_register(emu);
 3306                 imm = fetch_word_imm(emu);
 3307                 *destreg = imm;
 3308         }
 3309 }
 3310 
 3311 static void
 3312 x86emuOp_mov_word_RM_IMM(struct x86emu *emu)
 3313 {
 3314         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 3315                 x86emuOp32_mov_word_RM_IMM(emu);
 3316         else
 3317                 x86emuOp16_mov_word_RM_IMM(emu);
 3318 }
 3319 
 3320 /*
 3321  * REMARKS:
 3322  * Handles opcode 0xc8
 3323  */
 3324 static void
 3325 x86emuOp_enter(struct x86emu *emu)
 3326 {
 3327         uint16_t local, frame_pointer;
 3328         uint8_t nesting;
 3329         int i;
 3330 
 3331         local = fetch_word_imm(emu);
 3332         nesting = fetch_byte_imm(emu);
 3333         push_word(emu, emu->x86.R_BP);
 3334         frame_pointer = emu->x86.R_SP;
 3335         if (nesting > 0) {
 3336                 for (i = 1; i < nesting; i++) {
 3337                         emu->x86.R_BP -= 2;
 3338                         push_word(emu, fetch_word(emu, emu->x86.R_SS,
 3339                             emu->x86.R_BP));
 3340                 }
 3341                 push_word(emu, frame_pointer);
 3342         }
 3343         emu->x86.R_BP = frame_pointer;
 3344         emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
 3345 }
 3346 
 3347 /*
 3348  * REMARKS:
 3349  * Handles opcode 0xc9
 3350  */
 3351 static void
 3352 x86emuOp_leave(struct x86emu *emu)
 3353 {
 3354         emu->x86.R_SP = emu->x86.R_BP;
 3355         emu->x86.R_BP = pop_word(emu);
 3356 }
 3357 
 3358 /*
 3359  * REMARKS:
 3360  * Handles opcode 0xca
 3361  */
 3362 static void
 3363 x86emuOp_ret_far_IMM(struct x86emu *emu)
 3364 {
 3365         uint16_t imm;
 3366 
 3367         imm = fetch_word_imm(emu);
 3368         emu->x86.R_IP = pop_word(emu);
 3369         emu->x86.R_CS = pop_word(emu);
 3370         emu->x86.R_SP += imm;
 3371 }
 3372 
 3373 /*
 3374  * REMARKS:
 3375  * Handles opcode 0xcb
 3376  */
 3377 static void
 3378 x86emuOp_ret_far(struct x86emu *emu)
 3379 {
 3380         emu->x86.R_IP = pop_word(emu);
 3381         emu->x86.R_CS = pop_word(emu);
 3382 }
 3383 
 3384 /*
 3385  * REMARKS:
 3386  * Handles opcode 0xcc
 3387  */
 3388 static void
 3389 x86emuOp_int3(struct x86emu *emu)
 3390 {
 3391         x86emu_intr_dispatch(emu, 3);
 3392 }
 3393 
 3394 /*
 3395  * REMARKS:
 3396  * Handles opcode 0xcd
 3397  */
 3398 static void
 3399 x86emuOp_int_IMM(struct x86emu *emu)
 3400 {
 3401         uint8_t intnum;
 3402 
 3403         intnum = fetch_byte_imm(emu);
 3404         x86emu_intr_dispatch(emu, intnum);
 3405 }
 3406 
 3407 /*
 3408  * REMARKS:
 3409  * Handles opcode 0xce
 3410  */
 3411 static void
 3412 x86emuOp_into(struct x86emu *emu)
 3413 {
 3414         if (ACCESS_FLAG(F_OF))
 3415                 x86emu_intr_dispatch(emu, 4);
 3416 }
 3417 
 3418 /*
 3419  * REMARKS:
 3420  * Handles opcode 0xcf
 3421  */
 3422 static void
 3423 x86emuOp_iret(struct x86emu *emu)
 3424 {
 3425         emu->x86.R_IP = pop_word(emu);
 3426         emu->x86.R_CS = pop_word(emu);
 3427         emu->x86.R_FLG = pop_word(emu);
 3428 }
 3429 
 3430 /*
 3431  * REMARKS:
 3432  * Handles opcode 0xd0
 3433  */
 3434 static void
 3435 x86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
 3436 {
 3437         uint8_t destval;
 3438 
 3439         fetch_decode_modrm(emu);
 3440         destval = decode_and_fetch_byte(emu);
 3441         destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
 3442         write_back_byte(emu, destval);
 3443 }
 3444 
 3445 /*
 3446  * REMARKS:
 3447  * Handles opcode 0xd1
 3448  */
 3449 static void
 3450 x86emuOp_opcD1_word_RM_1(struct x86emu *emu)
 3451 {
 3452         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3453                 uint32_t destval;
 3454 
 3455                 fetch_decode_modrm(emu);
 3456                 destval = decode_and_fetch_long(emu);
 3457                 destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
 3458                 write_back_long(emu, destval);
 3459         } else {
 3460                 uint16_t destval;
 3461 
 3462                 fetch_decode_modrm(emu);
 3463                 destval = decode_and_fetch_word(emu);
 3464                 destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
 3465                 write_back_word(emu, destval);
 3466         }
 3467 }
 3468 
 3469 /*
 3470  * REMARKS:
 3471  * Handles opcode 0xd2
 3472  */
 3473 static void
 3474 x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
 3475 {
 3476         uint8_t destval;
 3477 
 3478         fetch_decode_modrm(emu);
 3479         destval = decode_and_fetch_byte(emu);
 3480         destval = (*opcD0_byte_operation[emu->cur_rh])
 3481             (emu, destval, emu->x86.R_CL);
 3482         write_back_byte(emu, destval);
 3483 }
 3484 
 3485 /*
 3486  * REMARKS:
 3487  * Handles opcode 0xd3
 3488  */
 3489 static void
 3490 x86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
 3491 {
 3492         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3493                 uint32_t destval;
 3494 
 3495                 fetch_decode_modrm(emu);
 3496                 destval = decode_and_fetch_long(emu);
 3497                 destval = (*opcD1_long_operation[emu->cur_rh])
 3498                     (emu, destval, emu->x86.R_CL);
 3499                 write_back_long(emu, destval);
 3500         } else {
 3501                 uint16_t destval;
 3502 
 3503                 fetch_decode_modrm(emu);
 3504                 destval = decode_and_fetch_word(emu);
 3505                 destval = (*opcD1_word_operation[emu->cur_rh])
 3506                     (emu, destval, emu->x86.R_CL);
 3507                 write_back_word(emu, destval);
 3508         }
 3509 }
 3510 
 3511 /*
 3512  * REMARKS:
 3513  * Handles opcode 0xd4
 3514  */
 3515 static void
 3516 x86emuOp_aam(struct x86emu *emu)
 3517 {
 3518         uint8_t a;
 3519 
 3520         a = fetch_byte_imm(emu);        /* this is a stupid encoding. */
 3521         if (a != 10) {
 3522                 /* fix: add base decoding aam_word(uint8_t val, int base a) */
 3523                 x86emu_halt_sys(emu);
 3524         }
 3525         /* note the type change here --- returning AL and AH in AX. */
 3526         emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
 3527 }
 3528 
 3529 /*
 3530  * REMARKS:
 3531  * Handles opcode 0xd5
 3532  */
 3533 static void
 3534 x86emuOp_aad(struct x86emu *emu)
 3535 {
 3536         uint8_t a;
 3537 
 3538         a = fetch_byte_imm(emu);
 3539         if (a != 10) {
 3540                 /* fix: add base decoding aad_word(uint16_t val, int base a) */
 3541                 x86emu_halt_sys(emu);
 3542         }
 3543         emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
 3544 }
 3545 /* opcode 0xd6 ILLEGAL OPCODE */
 3546 
 3547 
 3548 /*
 3549  * REMARKS:
 3550  * Handles opcode 0xd7
 3551  */
 3552 static void
 3553 x86emuOp_xlat(struct x86emu *emu)
 3554 {
 3555         uint16_t addr;
 3556 
 3557         addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
 3558         emu->x86.R_AL = fetch_data_byte(emu, addr);
 3559 }
 3560 
 3561 /* opcode=0xd8 */
 3562 static void 
 3563 x86emuOp_esc_coprocess_d8(struct x86emu *emu)
 3564 {
 3565 }
 3566 /* opcode=0xd9 */
 3567 static void 
 3568 x86emuOp_esc_coprocess_d9(struct x86emu *emu)
 3569 {
 3570         fetch_decode_modrm(emu);
 3571         if (emu->cur_mod != 3)
 3572                 decode_rl_address(emu);
 3573 }
 3574 /* opcode=0xda */
 3575 static void 
 3576 x86emuOp_esc_coprocess_da(struct x86emu *emu)
 3577 {
 3578         fetch_decode_modrm(emu);
 3579         if (emu->cur_mod != 3)
 3580                 decode_rl_address(emu);
 3581 }
 3582 /* opcode=0xdb */
 3583 static void 
 3584 x86emuOp_esc_coprocess_db(struct x86emu *emu)
 3585 {
 3586         fetch_decode_modrm(emu);
 3587         if (emu->cur_mod != 3)
 3588                 decode_rl_address(emu);
 3589 }
 3590 /* opcode=0xdc */
 3591 static void 
 3592 x86emuOp_esc_coprocess_dc(struct x86emu *emu)
 3593 {
 3594         fetch_decode_modrm(emu);
 3595         if (emu->cur_mod != 3)
 3596                 decode_rl_address(emu);
 3597 }
 3598 /* opcode=0xdd */
 3599 static void 
 3600 x86emuOp_esc_coprocess_dd(struct x86emu *emu)
 3601 {
 3602         fetch_decode_modrm(emu);
 3603         if (emu->cur_mod != 3)
 3604                 decode_rl_address(emu);
 3605 }
 3606 /* opcode=0xde */
 3607 static void 
 3608 x86emuOp_esc_coprocess_de(struct x86emu *emu)
 3609 {
 3610         fetch_decode_modrm(emu);
 3611         if (emu->cur_mod != 3)
 3612                 decode_rl_address(emu);
 3613 }
 3614 /* opcode=0xdf */
 3615 static void 
 3616 x86emuOp_esc_coprocess_df(struct x86emu *emu)
 3617 {
 3618         fetch_decode_modrm(emu);
 3619         if (emu->cur_mod != 3)
 3620                 decode_rl_address(emu);
 3621 }
 3622 
 3623 
 3624 /*
 3625  * REMARKS:
 3626  * Handles opcode 0xe0
 3627  */
 3628 static void
 3629 x86emuOp_loopne(struct x86emu *emu)
 3630 {
 3631         int16_t ip;
 3632 
 3633         ip = (int8_t) fetch_byte_imm(emu);
 3634         ip += (int16_t) emu->x86.R_IP;
 3635         emu->x86.R_CX -= 1;
 3636         if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))   /* CX != 0 and !ZF */
 3637                 emu->x86.R_IP = ip;
 3638 }
 3639 
 3640 /*
 3641  * REMARKS:
 3642  * Handles opcode 0xe1
 3643  */
 3644 static void
 3645 x86emuOp_loope(struct x86emu *emu)
 3646 {
 3647         int16_t ip;
 3648 
 3649         ip = (int8_t) fetch_byte_imm(emu);
 3650         ip += (int16_t) emu->x86.R_IP;
 3651         emu->x86.R_CX -= 1;
 3652         if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF))    /* CX != 0 and ZF */
 3653                 emu->x86.R_IP = ip;
 3654 }
 3655 
 3656 /*
 3657  * REMARKS:
 3658  * Handles opcode 0xe2
 3659  */
 3660 static void
 3661 x86emuOp_loop(struct x86emu *emu)
 3662 {
 3663         int16_t ip;
 3664 
 3665         ip = (int8_t) fetch_byte_imm(emu);
 3666         ip += (int16_t) emu->x86.R_IP;
 3667         emu->x86.R_CX -= 1;
 3668         if (emu->x86.R_CX != 0)
 3669                 emu->x86.R_IP = ip;
 3670 }
 3671 
 3672 /*
 3673  * REMARKS:
 3674  * Handles opcode 0xe3
 3675  */
 3676 static void
 3677 x86emuOp_jcxz(struct x86emu *emu)
 3678 {
 3679         uint16_t target;
 3680         int8_t offset;
 3681 
 3682         /* jump to byte offset if overflow flag is set */
 3683         offset = (int8_t) fetch_byte_imm(emu);
 3684         target = (uint16_t) (emu->x86.R_IP + offset);
 3685         if (emu->x86.R_CX == 0)
 3686                 emu->x86.R_IP = target;
 3687 }
 3688 
 3689 /*
 3690  * REMARKS:
 3691  * Handles opcode 0xe4
 3692  */
 3693 static void
 3694 x86emuOp_in_byte_AL_IMM(struct x86emu *emu)
 3695 {
 3696         uint8_t port;
 3697 
 3698         port = (uint8_t) fetch_byte_imm(emu);
 3699         emu->x86.R_AL = (*emu->emu_inb) (emu, port);
 3700 }
 3701 
 3702 /*
 3703  * REMARKS:
 3704  * Handles opcode 0xe5
 3705  */
 3706 static void
 3707 x86emuOp_in_word_AX_IMM(struct x86emu *emu)
 3708 {
 3709         uint8_t port;
 3710 
 3711         port = (uint8_t) fetch_byte_imm(emu);
 3712         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3713                 emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
 3714         } else {
 3715                 emu->x86.R_AX = (*emu->emu_inw) (emu, port);
 3716         }
 3717 }
 3718 
 3719 /*
 3720  * REMARKS:
 3721  * Handles opcode 0xe6
 3722  */
 3723 static void
 3724 x86emuOp_out_byte_IMM_AL(struct x86emu *emu)
 3725 {
 3726         uint8_t port;
 3727 
 3728         port = (uint8_t) fetch_byte_imm(emu);
 3729         (*emu->emu_outb) (emu, port, emu->x86.R_AL);
 3730 }
 3731 
 3732 /*
 3733  * REMARKS:
 3734  * Handles opcode 0xe7
 3735  */
 3736 static void
 3737 x86emuOp_out_word_IMM_AX(struct x86emu *emu)
 3738 {
 3739         uint8_t port;
 3740 
 3741         port = (uint8_t) fetch_byte_imm(emu);
 3742         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3743                 (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
 3744         } else {
 3745                 (*emu->emu_outw) (emu, port, emu->x86.R_AX);
 3746         }
 3747 }
 3748 
 3749 /*
 3750  * REMARKS:
 3751  * Handles opcode 0xe8
 3752  */
 3753 static void
 3754 x86emuOp_call_near_IMM(struct x86emu *emu)
 3755 {
 3756         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3757                 int32_t ip;
 3758                 ip = (int32_t) fetch_long_imm(emu);
 3759                 ip += (int32_t) emu->x86.R_EIP;
 3760                 push_long(emu, emu->x86.R_EIP);
 3761                 emu->x86.R_EIP = ip;
 3762         } else {
 3763                 int16_t ip;
 3764                 ip = (int16_t) fetch_word_imm(emu);
 3765                 ip += (int16_t) emu->x86.R_IP;  /* CHECK SIGN */
 3766                 push_word(emu, emu->x86.R_IP);
 3767                 emu->x86.R_IP = ip;
 3768         }
 3769 }
 3770 
 3771 /*
 3772  * REMARKS:
 3773  * Handles opcode 0xe9
 3774  */
 3775 static void
 3776 x86emuOp_jump_near_IMM(struct x86emu *emu)
 3777 {
 3778         int ip;
 3779 
 3780         ip = (int16_t) fetch_word_imm(emu);
 3781         ip += (int16_t) emu->x86.R_IP;
 3782         emu->x86.R_IP = (uint16_t) ip;
 3783 }
 3784 
 3785 /*
 3786  * REMARKS:
 3787  * Handles opcode 0xea
 3788  */
 3789 static void
 3790 x86emuOp_jump_far_IMM(struct x86emu *emu)
 3791 {
 3792         uint16_t cs, ip;
 3793 
 3794         ip = fetch_word_imm(emu);
 3795         cs = fetch_word_imm(emu);
 3796         emu->x86.R_IP = ip;
 3797         emu->x86.R_CS = cs;
 3798 }
 3799 
 3800 /*
 3801  * REMARKS:
 3802  * Handles opcode 0xeb
 3803  */
 3804 static void
 3805 x86emuOp_jump_byte_IMM(struct x86emu *emu)
 3806 {
 3807         uint16_t target;
 3808         int8_t offset;
 3809 
 3810         offset = (int8_t) fetch_byte_imm(emu);
 3811         target = (uint16_t) (emu->x86.R_IP + offset);
 3812         emu->x86.R_IP = target;
 3813 }
 3814 
 3815 /*
 3816  * REMARKS:
 3817  * Handles opcode 0xec
 3818  */
 3819 static void
 3820 x86emuOp_in_byte_AL_DX(struct x86emu *emu)
 3821 {
 3822         emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
 3823 }
 3824 
 3825 /*
 3826  * REMARKS:
 3827  * Handles opcode 0xed
 3828  */
 3829 static void
 3830 x86emuOp_in_word_AX_DX(struct x86emu *emu)
 3831 {
 3832         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3833                 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
 3834         } else {
 3835                 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
 3836         }
 3837 }
 3838 
 3839 /*
 3840  * REMARKS:
 3841  * Handles opcode 0xee
 3842  */
 3843 static void
 3844 x86emuOp_out_byte_DX_AL(struct x86emu *emu)
 3845 {
 3846         (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
 3847 }
 3848 
 3849 /*
 3850  * REMARKS:
 3851  * Handles opcode 0xef
 3852  */
 3853 static void
 3854 x86emuOp_out_word_DX_AX(struct x86emu *emu)
 3855 {
 3856         if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 3857                 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
 3858         } else {
 3859                 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
 3860         }
 3861 }
 3862 
 3863 /*
 3864  * REMARKS:
 3865  * Handles opcode 0xf0
 3866  */
 3867 static void
 3868 x86emuOp_lock(struct x86emu *emu)
 3869 {
 3870 }
 3871 /*opcode 0xf1 ILLEGAL OPERATION */
 3872 
 3873 
 3874 /*
 3875  * REMARKS:
 3876  * Handles opcode 0xf5
 3877  */
 3878 static void
 3879 x86emuOp_cmc(struct x86emu *emu)
 3880 {
 3881         if (ACCESS_FLAG(F_CF))
 3882                 CLEAR_FLAG(F_CF);
 3883         else
 3884                 SET_FLAG(F_CF);
 3885 }
 3886 
 3887 /*
 3888  * REMARKS:
 3889  * Handles opcode 0xf6
 3890  */
 3891 static void
 3892 x86emuOp_opcF6_byte_RM(struct x86emu *emu)
 3893 {
 3894         uint8_t destval, srcval;
 3895 
 3896         /* long, drawn out code follows.  Double switch for a total of 32
 3897          * cases.  */
 3898         fetch_decode_modrm(emu);
 3899         if (emu->cur_rh == 1)
 3900                 x86emu_halt_sys(emu);
 3901 
 3902         if (emu->cur_rh == 0) {
 3903                 destval = decode_and_fetch_byte_imm8(emu, &srcval);
 3904                 test_byte(emu, destval, srcval);
 3905                 return;
 3906         }
 3907         destval = decode_and_fetch_byte(emu);
 3908         switch (emu->cur_rh) {
 3909         case 2:
 3910                 destval = ~destval;
 3911                 write_back_byte(emu, destval);
 3912                 break;
 3913         case 3:
 3914                 destval = neg_byte(emu, destval);
 3915                 write_back_byte(emu, destval);
 3916                 break;
 3917         case 4:
 3918                 mul_byte(emu, destval);
 3919                 break;
 3920         case 5:
 3921                 imul_byte(emu, destval);
 3922                 break;
 3923         case 6:
 3924                 div_byte(emu, destval);
 3925                 break;
 3926         case 7:
 3927                 idiv_byte(emu, destval);
 3928                 break;
 3929         }
 3930 }
 3931 
 3932 /*
 3933  * REMARKS:
 3934  * Handles opcode 0xf7
 3935  */
 3936 static void
 3937 x86emuOp32_opcF7_word_RM(struct x86emu *emu)
 3938 {
 3939         uint32_t destval, srcval;
 3940 
 3941         /* long, drawn out code follows.  Double switch for a total of 32
 3942          * cases.  */
 3943         fetch_decode_modrm(emu);
 3944         if (emu->cur_rh == 1)
 3945                 x86emu_halt_sys(emu);
 3946 
 3947         if (emu->cur_rh == 0) {
 3948                 if (emu->cur_mod != 3) {
 3949                         uint32_t destoffset;
 3950 
 3951                         destoffset = decode_rl_address(emu);
 3952                         srcval = fetch_long_imm(emu);
 3953                         destval = fetch_data_long(emu, destoffset);
 3954                 } else {
 3955                         srcval = fetch_long_imm(emu);
 3956                         destval = *decode_rl_long_register(emu);
 3957                 }
 3958                 test_long(emu, destval, srcval);
 3959                 return;
 3960         }
 3961         destval = decode_and_fetch_long(emu);
 3962         switch (emu->cur_rh) {
 3963         case 2:
 3964                 destval = ~destval;
 3965                 write_back_long(emu, destval);
 3966                 break;
 3967         case 3:
 3968                 destval = neg_long(emu, destval);
 3969                 write_back_long(emu, destval);
 3970                 break;
 3971         case 4:
 3972                 mul_long(emu, destval);
 3973                 break;
 3974         case 5:
 3975                 imul_long(emu, destval);
 3976                 break;
 3977         case 6:
 3978                 div_long(emu, destval);
 3979                 break;
 3980         case 7:
 3981                 idiv_long(emu, destval);
 3982                 break;
 3983         }
 3984 }
 3985 static void
 3986 x86emuOp16_opcF7_word_RM(struct x86emu *emu)
 3987 {
 3988         uint16_t destval, srcval;
 3989 
 3990         /* long, drawn out code follows.  Double switch for a total of 32
 3991          * cases.  */
 3992         fetch_decode_modrm(emu);
 3993         if (emu->cur_rh == 1)
 3994                 x86emu_halt_sys(emu);
 3995 
 3996         if (emu->cur_rh == 0) {
 3997                 if (emu->cur_mod != 3) {
 3998                         uint32_t destoffset;
 3999 
 4000                         destoffset = decode_rl_address(emu);
 4001                         srcval = fetch_word_imm(emu);
 4002                         destval = fetch_data_word(emu, destoffset);
 4003                 } else {
 4004                         srcval = fetch_word_imm(emu);
 4005                         destval = *decode_rl_word_register(emu);
 4006                 }
 4007                 test_word(emu, destval, srcval);
 4008                 return;
 4009         }
 4010         destval = decode_and_fetch_word(emu);
 4011         switch (emu->cur_rh) {
 4012         case 2:
 4013                 destval = ~destval;
 4014                 write_back_word(emu, destval);
 4015                 break;
 4016         case 3:
 4017                 destval = neg_word(emu, destval);
 4018                 write_back_word(emu, destval);
 4019                 break;
 4020         case 4:
 4021                 mul_word(emu, destval);
 4022                 break;
 4023         case 5:
 4024                 imul_word(emu, destval);
 4025                 break;
 4026         case 6:
 4027                 div_word(emu, destval);
 4028                 break;
 4029         case 7:
 4030                 idiv_word(emu, destval);
 4031                 break;
 4032         }
 4033 }
 4034 static void
 4035 x86emuOp_opcF7_word_RM(struct x86emu *emu)
 4036 {
 4037         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 4038                 x86emuOp32_opcF7_word_RM(emu);
 4039         else
 4040                 x86emuOp16_opcF7_word_RM(emu);
 4041 }
 4042 
 4043 /*
 4044  * REMARKS:
 4045  * Handles opcode 0xfe
 4046  */
 4047 static void
 4048 x86emuOp_opcFE_byte_RM(struct x86emu *emu)
 4049 {
 4050         uint8_t destval;
 4051         uint32_t destoffset;
 4052         uint8_t *destreg;
 4053 
 4054         /* Yet another special case instruction. */
 4055         fetch_decode_modrm(emu);
 4056         if (emu->cur_mod != 3) {
 4057                 destoffset = decode_rl_address(emu);
 4058                 switch (emu->cur_rh) {
 4059                 case 0: /* inc word ptr ... */
 4060                         destval = fetch_data_byte(emu, destoffset);
 4061                         destval = inc_byte(emu, destval);
 4062                         store_data_byte(emu, destoffset, destval);
 4063                         break;
 4064                 case 1: /* dec word ptr ... */
 4065                         destval = fetch_data_byte(emu, destoffset);
 4066                         destval = dec_byte(emu, destval);
 4067                         store_data_byte(emu, destoffset, destval);
 4068                         break;
 4069                 }
 4070         } else {
 4071                 destreg = decode_rl_byte_register(emu);
 4072                 switch (emu->cur_rh) {
 4073                 case 0:
 4074                         *destreg = inc_byte(emu, *destreg);
 4075                         break;
 4076                 case 1:
 4077                         *destreg = dec_byte(emu, *destreg);
 4078                         break;
 4079                 }
 4080         }
 4081 }
 4082 
 4083 /*
 4084  * REMARKS:
 4085  * Handles opcode 0xff
 4086  */
 4087 static void
 4088 x86emuOp32_opcFF_word_RM(struct x86emu *emu)
 4089 {
 4090         uint32_t destoffset = 0;
 4091         uint32_t destval, *destreg;
 4092 
 4093         if (emu->cur_mod != 3) {
 4094                 destoffset = decode_rl_address(emu);
 4095                 destval = fetch_data_long(emu, destoffset);
 4096                 switch (emu->cur_rh) {
 4097                 case 0: /* inc word ptr ... */
 4098                         destval = inc_long(emu, destval);
 4099                         store_data_long(emu, destoffset, destval);
 4100                         break;
 4101                 case 1: /* dec word ptr ... */
 4102                         destval = dec_long(emu, destval);
 4103                         store_data_long(emu, destoffset, destval);
 4104                         break;
 4105                 case 6: /* push word ptr ... */
 4106                         push_long(emu, destval);
 4107                         break;
 4108                 }
 4109         } else {
 4110                 destreg = decode_rl_long_register(emu);
 4111                 switch (emu->cur_rh) {
 4112                 case 0:
 4113                         *destreg = inc_long(emu, *destreg);
 4114                         break;
 4115                 case 1:
 4116                         *destreg = dec_long(emu, *destreg);
 4117                         break;
 4118                 case 6:
 4119                         push_long(emu, *destreg);
 4120                         break;
 4121                 }
 4122         }
 4123 }
 4124 
 4125 static void
 4126 x86emuOp16_opcFF_word_RM(struct x86emu *emu)
 4127 {
 4128         uint32_t destoffset = 0;
 4129         uint16_t *destreg;
 4130         uint16_t destval;
 4131 
 4132         if (emu->cur_mod != 3) {
 4133                 destoffset = decode_rl_address(emu);
 4134                 destval = fetch_data_word(emu, destoffset);
 4135                 switch (emu->cur_rh) {
 4136                 case 0:
 4137                         destval = inc_word(emu, destval);
 4138                         store_data_word(emu, destoffset, destval);
 4139                         break;
 4140                 case 1: /* dec word ptr ... */
 4141                         destval = dec_word(emu, destval);
 4142                         store_data_word(emu, destoffset, destval);
 4143                         break;
 4144                 case 6: /* push word ptr ... */
 4145                         push_word(emu, destval);
 4146                         break;
 4147                 }
 4148         } else {
 4149                 destreg = decode_rl_word_register(emu);
 4150                 switch (emu->cur_rh) {
 4151                 case 0:
 4152                         *destreg = inc_word(emu, *destreg);
 4153                         break;
 4154                 case 1:
 4155                         *destreg = dec_word(emu, *destreg);
 4156                         break;
 4157                 case 6:
 4158                         push_word(emu, *destreg);
 4159                         break;
 4160                 }
 4161         }
 4162 }
 4163 
 4164 static void
 4165 x86emuOp_opcFF_word_RM(struct x86emu *emu)
 4166 {
 4167         uint32_t destoffset = 0;
 4168         uint16_t destval, destval2;
 4169 
 4170         /* Yet another special case instruction. */
 4171         fetch_decode_modrm(emu);
 4172         if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
 4173             emu->cur_rh == 7)
 4174                 x86emu_halt_sys(emu);
 4175         if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
 4176                 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 4177                         x86emuOp32_opcFF_word_RM(emu);
 4178                 else
 4179                         x86emuOp16_opcFF_word_RM(emu);
 4180                 return;
 4181         }
 4182 
 4183         if (emu->cur_mod != 3) {
 4184                 destoffset = decode_rl_address(emu);
 4185                 destval = fetch_data_word(emu, destoffset);
 4186                 switch (emu->cur_rh) {
 4187                 case 3: /* call far ptr ... */
 4188                         destval2 = fetch_data_word(emu, destoffset + 2);
 4189                         push_word(emu, emu->x86.R_CS);
 4190                         emu->x86.R_CS = destval2;
 4191                         push_word(emu, emu->x86.R_IP);
 4192                         emu->x86.R_IP = destval;
 4193                         break;
 4194                 case 5: /* jmp far ptr ... */
 4195                         destval2 = fetch_data_word(emu, destoffset + 2);
 4196                         emu->x86.R_IP = destval;
 4197                         emu->x86.R_CS = destval2;
 4198                         break;
 4199                 }
 4200         } else {
 4201                 destval = *decode_rl_word_register(emu);
 4202         }
 4203 
 4204         switch (emu->cur_rh) {
 4205         case 2: /* call word ptr */
 4206                 push_word(emu, emu->x86.R_IP);
 4207                 emu->x86.R_IP = destval;
 4208                 break;
 4209         case 4: /* jmp */
 4210                 emu->x86.R_IP = destval;
 4211                 break;
 4212         }
 4213 }
 4214 
 4215 /*
 4216  *  * Single byte operation code table:
 4217  */
 4218 static void
 4219 x86emu_exec_one_byte(struct x86emu * emu)
 4220 {
 4221         uint8_t op1;
 4222 
 4223         op1 = fetch_byte_imm(emu);
 4224 
 4225         switch (op1) {
 4226         case 0x00:
 4227                 common_binop_byte_rm_r(emu, add_byte);
 4228                 break;
 4229         case 0x01:
 4230                 common_binop_word_long_rm_r(emu, add_word, add_long);
 4231                 break;
 4232         case 0x02:
 4233                 common_binop_byte_r_rm(emu, add_byte);
 4234                 break;
 4235         case 0x03:
 4236                 common_binop_word_long_r_rm(emu, add_word, add_long);
 4237                 break;
 4238         case 0x04:
 4239                 common_binop_byte_imm(emu, add_byte);
 4240                 break;
 4241         case 0x05:
 4242                 common_binop_word_long_imm(emu, add_word, add_long);
 4243                 break;
 4244         case 0x06:
 4245                 push_word(emu, emu->x86.R_ES);
 4246                 break;
 4247         case 0x07:
 4248                 emu->x86.R_ES = pop_word(emu);
 4249                 break;
 4250 
 4251         case 0x08:
 4252                 common_binop_byte_rm_r(emu, or_byte);
 4253                 break;
 4254         case 0x09:
 4255                 common_binop_word_long_rm_r(emu, or_word, or_long);
 4256                 break;
 4257         case 0x0a:
 4258                 common_binop_byte_r_rm(emu, or_byte);
 4259                 break;
 4260         case 0x0b:
 4261                 common_binop_word_long_r_rm(emu, or_word, or_long);
 4262                 break;
 4263         case 0x0c:
 4264                 common_binop_byte_imm(emu, or_byte);
 4265                 break;
 4266         case 0x0d:
 4267                 common_binop_word_long_imm(emu, or_word, or_long);
 4268                 break;
 4269         case 0x0e:
 4270                 push_word(emu, emu->x86.R_CS);
 4271                 break;
 4272         case 0x0f:
 4273                 x86emu_exec_two_byte(emu);
 4274                 break;
 4275 
 4276         case 0x10:
 4277                 common_binop_byte_rm_r(emu, adc_byte);
 4278                 break;
 4279         case 0x11:
 4280                 common_binop_word_long_rm_r(emu, adc_word, adc_long);
 4281                 break;
 4282         case 0x12:
 4283                 common_binop_byte_r_rm(emu, adc_byte);
 4284                 break;
 4285         case 0x13:
 4286                 common_binop_word_long_r_rm(emu, adc_word, adc_long);
 4287                 break;
 4288         case 0x14:
 4289                 common_binop_byte_imm(emu, adc_byte);
 4290                 break;
 4291         case 0x15:
 4292                 common_binop_word_long_imm(emu, adc_word, adc_long);
 4293                 break;
 4294         case 0x16:
 4295                 push_word(emu, emu->x86.R_SS);
 4296                 break;
 4297         case 0x17:
 4298                 emu->x86.R_SS = pop_word(emu);
 4299                 break;
 4300 
 4301         case 0x18:
 4302                 common_binop_byte_rm_r(emu, sbb_byte);
 4303                 break;
 4304         case 0x19:
 4305                 common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
 4306                 break;
 4307         case 0x1a:
 4308                 common_binop_byte_r_rm(emu, sbb_byte);
 4309                 break;
 4310         case 0x1b:
 4311                 common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
 4312                 break;
 4313         case 0x1c:
 4314                 common_binop_byte_imm(emu, sbb_byte);
 4315                 break;
 4316         case 0x1d:
 4317                 common_binop_word_long_imm(emu, sbb_word, sbb_long);
 4318                 break;
 4319         case 0x1e:
 4320                 push_word(emu, emu->x86.R_DS);
 4321                 break;
 4322         case 0x1f:
 4323                 emu->x86.R_DS = pop_word(emu);
 4324                 break;
 4325 
 4326         case 0x20:
 4327                 common_binop_byte_rm_r(emu, and_byte);
 4328                 break;
 4329         case 0x21:
 4330                 common_binop_word_long_rm_r(emu, and_word, and_long);
 4331                 break;
 4332         case 0x22:
 4333                 common_binop_byte_r_rm(emu, and_byte);
 4334                 break;
 4335         case 0x23:
 4336                 common_binop_word_long_r_rm(emu, and_word, and_long);
 4337                 break;
 4338         case 0x24:
 4339                 common_binop_byte_imm(emu, and_byte);
 4340                 break;
 4341         case 0x25:
 4342                 common_binop_word_long_imm(emu, and_word, and_long);
 4343                 break;
 4344         case 0x26:
 4345                 emu->x86.mode |= SYSMODE_SEGOVR_ES;
 4346                 break;
 4347         case 0x27:
 4348                 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
 4349                 break;
 4350 
 4351         case 0x28:
 4352                 common_binop_byte_rm_r(emu, sub_byte);
 4353                 break;
 4354         case 0x29:
 4355                 common_binop_word_long_rm_r(emu, sub_word, sub_long);
 4356                 break;
 4357         case 0x2a:
 4358                 common_binop_byte_r_rm(emu, sub_byte);
 4359                 break;
 4360         case 0x2b:
 4361                 common_binop_word_long_r_rm(emu, sub_word, sub_long);
 4362                 break;
 4363         case 0x2c:
 4364                 common_binop_byte_imm(emu, sub_byte);
 4365                 break;
 4366         case 0x2d:
 4367                 common_binop_word_long_imm(emu, sub_word, sub_long);
 4368                 break;
 4369         case 0x2e:
 4370                 emu->x86.mode |= SYSMODE_SEGOVR_CS;
 4371                 break;
 4372         case 0x2f:
 4373                 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
 4374                 break;
 4375 
 4376         case 0x30:
 4377                 common_binop_byte_rm_r(emu, xor_byte);
 4378                 break;
 4379         case 0x31:
 4380                 common_binop_word_long_rm_r(emu, xor_word, xor_long);
 4381                 break;
 4382         case 0x32:
 4383                 common_binop_byte_r_rm(emu, xor_byte);
 4384                 break;
 4385         case 0x33:
 4386                 common_binop_word_long_r_rm(emu, xor_word, xor_long);
 4387                 break;
 4388         case 0x34:
 4389                 common_binop_byte_imm(emu, xor_byte);
 4390                 break;
 4391         case 0x35:
 4392                 common_binop_word_long_imm(emu, xor_word, xor_long);
 4393                 break;
 4394         case 0x36:
 4395                 emu->x86.mode |= SYSMODE_SEGOVR_SS;
 4396                 break;
 4397         case 0x37:
 4398                 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
 4399                 break;
 4400 
 4401         case 0x38:
 4402                 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
 4403                 break;
 4404         case 0x39:
 4405                 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
 4406                     cmp_long_no_return);
 4407                 break;
 4408         case 0x3a:
 4409                 x86emuOp_cmp_byte_R_RM(emu);
 4410                 break;
 4411         case 0x3b:
 4412                 x86emuOp_cmp_word_R_RM(emu);
 4413                 break;
 4414         case 0x3c:
 4415                 x86emuOp_cmp_byte_AL_IMM(emu);
 4416                 break;
 4417         case 0x3d:
 4418                 x86emuOp_cmp_word_AX_IMM(emu);
 4419                 break;
 4420         case 0x3e:
 4421                 emu->x86.mode |= SYSMODE_SEGOVR_DS;
 4422                 break;
 4423         case 0x3f:
 4424                 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
 4425                 break;
 4426 
 4427         case 0x40:
 4428                 common_inc_word_long(emu, &emu->x86.register_a);
 4429                 break;
 4430         case 0x41:
 4431                 common_inc_word_long(emu, &emu->x86.register_c);
 4432                 break;
 4433         case 0x42:
 4434                 common_inc_word_long(emu, &emu->x86.register_d);
 4435                 break;
 4436         case 0x43:
 4437                 common_inc_word_long(emu, &emu->x86.register_b);
 4438                 break;
 4439         case 0x44:
 4440                 common_inc_word_long(emu, &emu->x86.register_sp);
 4441                 break;
 4442         case 0x45:
 4443                 common_inc_word_long(emu, &emu->x86.register_bp);
 4444                 break;
 4445         case 0x46:
 4446                 common_inc_word_long(emu, &emu->x86.register_si);
 4447                 break;
 4448         case 0x47:
 4449                 common_inc_word_long(emu, &emu->x86.register_di);
 4450                 break;
 4451 
 4452         case 0x48:
 4453                 common_dec_word_long(emu, &emu->x86.register_a);
 4454                 break;
 4455         case 0x49:
 4456                 common_dec_word_long(emu, &emu->x86.register_c);
 4457                 break;
 4458         case 0x4a:
 4459                 common_dec_word_long(emu, &emu->x86.register_d);
 4460                 break;
 4461         case 0x4b:
 4462                 common_dec_word_long(emu, &emu->x86.register_b);
 4463                 break;
 4464         case 0x4c:
 4465                 common_dec_word_long(emu, &emu->x86.register_sp);
 4466                 break;
 4467         case 0x4d:
 4468                 common_dec_word_long(emu, &emu->x86.register_bp);
 4469                 break;
 4470         case 0x4e:
 4471                 common_dec_word_long(emu, &emu->x86.register_si);
 4472                 break;
 4473         case 0x4f:
 4474                 common_dec_word_long(emu, &emu->x86.register_di);
 4475                 break;
 4476 
 4477         case 0x50:
 4478                 common_push_word_long(emu, &emu->x86.register_a);
 4479                 break;
 4480         case 0x51:
 4481                 common_push_word_long(emu, &emu->x86.register_c);
 4482                 break;
 4483         case 0x52:
 4484                 common_push_word_long(emu, &emu->x86.register_d);
 4485                 break;
 4486         case 0x53:
 4487                 common_push_word_long(emu, &emu->x86.register_b);
 4488                 break;
 4489         case 0x54:
 4490                 common_push_word_long(emu, &emu->x86.register_sp);
 4491                 break;
 4492         case 0x55:
 4493                 common_push_word_long(emu, &emu->x86.register_bp);
 4494                 break;
 4495         case 0x56:
 4496                 common_push_word_long(emu, &emu->x86.register_si);
 4497                 break;
 4498         case 0x57:
 4499                 common_push_word_long(emu, &emu->x86.register_di);
 4500                 break;
 4501 
 4502         case 0x58:
 4503                 common_pop_word_long(emu, &emu->x86.register_a);
 4504                 break;
 4505         case 0x59:
 4506                 common_pop_word_long(emu, &emu->x86.register_c);
 4507                 break;
 4508         case 0x5a:
 4509                 common_pop_word_long(emu, &emu->x86.register_d);
 4510                 break;
 4511         case 0x5b:
 4512                 common_pop_word_long(emu, &emu->x86.register_b);
 4513                 break;
 4514         case 0x5c:
 4515                 common_pop_word_long(emu, &emu->x86.register_sp);
 4516                 break;
 4517         case 0x5d:
 4518                 common_pop_word_long(emu, &emu->x86.register_bp);
 4519                 break;
 4520         case 0x5e:
 4521                 common_pop_word_long(emu, &emu->x86.register_si);
 4522                 break;
 4523         case 0x5f:
 4524                 common_pop_word_long(emu, &emu->x86.register_di);
 4525                 break;
 4526 
 4527         case 0x60:
 4528                 x86emuOp_push_all(emu);
 4529                 break;
 4530         case 0x61:
 4531                 x86emuOp_pop_all(emu);
 4532                 break;
 4533         /* 0x62 bound */
 4534         /* 0x63 arpl */
 4535         case 0x64:
 4536                 emu->x86.mode |= SYSMODE_SEGOVR_FS;
 4537                 break;
 4538         case 0x65:
 4539                 emu->x86.mode |= SYSMODE_SEGOVR_GS;
 4540                 break;
 4541         case 0x66:
 4542                 emu->x86.mode |= SYSMODE_PREFIX_DATA;
 4543                 break;
 4544         case 0x67:
 4545                 emu->x86.mode |= SYSMODE_PREFIX_ADDR;
 4546                 break;
 4547 
 4548         case 0x68:
 4549                 x86emuOp_push_word_IMM(emu);
 4550                 break;
 4551         case 0x69:
 4552                 common_imul_imm(emu, 0);
 4553                 break;
 4554         case 0x6a:
 4555                 x86emuOp_push_byte_IMM(emu);
 4556                 break;
 4557         case 0x6b:
 4558                 common_imul_imm(emu, 1);
 4559                 break;
 4560         case 0x6c:
 4561                 ins(emu, 1);
 4562                 break;
 4563         case 0x6d:
 4564                 x86emuOp_ins_word(emu);
 4565                 break;
 4566         case 0x6e:
 4567                 outs(emu, 1);
 4568                 break;
 4569         case 0x6f:
 4570                 x86emuOp_outs_word(emu);
 4571                 break;
 4572 
 4573         case 0x70:
 4574                 common_jmp_near(emu, ACCESS_FLAG(F_OF));
 4575                 break;
 4576         case 0x71:
 4577                 common_jmp_near(emu, !ACCESS_FLAG(F_OF));
 4578                 break;
 4579         case 0x72:
 4580                 common_jmp_near(emu, ACCESS_FLAG(F_CF));
 4581                 break;
 4582         case 0x73:
 4583                 common_jmp_near(emu, !ACCESS_FLAG(F_CF));
 4584                 break;
 4585         case 0x74:
 4586                 common_jmp_near(emu, ACCESS_FLAG(F_ZF));
 4587                 break;
 4588         case 0x75:
 4589                 common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
 4590                 break;
 4591         case 0x76:
 4592                 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
 4593                 break;
 4594         case 0x77:
 4595                 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
 4596                 break;
 4597 
 4598         case 0x78:
 4599                 common_jmp_near(emu, ACCESS_FLAG(F_SF));
 4600                 break;
 4601         case 0x79:
 4602                 common_jmp_near(emu, !ACCESS_FLAG(F_SF));
 4603                 break;
 4604         case 0x7a:
 4605                 common_jmp_near(emu, ACCESS_FLAG(F_PF));
 4606                 break;
 4607         case 0x7b:
 4608                 common_jmp_near(emu, !ACCESS_FLAG(F_PF));
 4609                 break;
 4610         case 0x7c:
 4611                 x86emuOp_jump_near_L(emu);
 4612                 break;
 4613         case 0x7d:
 4614                 x86emuOp_jump_near_NL(emu);
 4615                 break;
 4616         case 0x7e:
 4617                 x86emuOp_jump_near_LE(emu);
 4618                 break;
 4619         case 0x7f:
 4620                 x86emuOp_jump_near_NLE(emu);
 4621                 break;
 4622 
 4623         case 0x80:
 4624                 x86emuOp_opc80_byte_RM_IMM(emu);
 4625                 break;
 4626         case 0x81:
 4627                 x86emuOp_opc81_word_RM_IMM(emu);
 4628                 break;
 4629         case 0x82:
 4630                 x86emuOp_opc82_byte_RM_IMM(emu);
 4631                 break;
 4632         case 0x83:
 4633                 x86emuOp_opc83_word_RM_IMM(emu);
 4634                 break;
 4635         case 0x84:
 4636                 common_binop_ns_byte_rm_r(emu, test_byte);
 4637                 break;
 4638         case 0x85:
 4639                 common_binop_ns_word_long_rm_r(emu, test_word, test_long);
 4640                 break;
 4641         case 0x86:
 4642                 x86emuOp_xchg_byte_RM_R(emu);
 4643                 break;
 4644         case 0x87:
 4645                 x86emuOp_xchg_word_RM_R(emu);
 4646                 break;
 4647 
 4648         case 0x88:
 4649                 x86emuOp_mov_byte_RM_R(emu);
 4650                 break;
 4651         case 0x89:
 4652                 x86emuOp_mov_word_RM_R(emu);
 4653                 break;
 4654         case 0x8a:
 4655                 x86emuOp_mov_byte_R_RM(emu);
 4656                 break;
 4657         case 0x8b:
 4658                 x86emuOp_mov_word_R_RM(emu);
 4659                 break;
 4660         case 0x8c:
 4661                 x86emuOp_mov_word_RM_SR(emu);
 4662                 break;
 4663         case 0x8d:
 4664                 x86emuOp_lea_word_R_M(emu);
 4665                 break;
 4666         case 0x8e:
 4667                 x86emuOp_mov_word_SR_RM(emu);
 4668                 break;
 4669         case 0x8f:
 4670                 x86emuOp_pop_RM(emu);
 4671                 break;
 4672 
 4673         case 0x90:
 4674                 /* nop */
 4675                 break;
 4676         case 0x91:
 4677                 x86emuOp_xchg_word_AX_CX(emu);
 4678                 break;
 4679         case 0x92:
 4680                 x86emuOp_xchg_word_AX_DX(emu);
 4681                 break;
 4682         case 0x93:
 4683                 x86emuOp_xchg_word_AX_BX(emu);
 4684                 break;
 4685         case 0x94:
 4686                 x86emuOp_xchg_word_AX_SP(emu);
 4687                 break;
 4688         case 0x95:
 4689                 x86emuOp_xchg_word_AX_BP(emu);
 4690                 break;
 4691         case 0x96:
 4692                 x86emuOp_xchg_word_AX_SI(emu);
 4693                 break;
 4694         case 0x97:
 4695                 x86emuOp_xchg_word_AX_DI(emu);
 4696                 break;
 4697 
 4698         case 0x98:
 4699                 x86emuOp_cbw(emu);
 4700                 break;
 4701         case 0x99:
 4702                 x86emuOp_cwd(emu);
 4703                 break;
 4704         case 0x9a:
 4705                 x86emuOp_call_far_IMM(emu);
 4706                 break;
 4707         case 0x9b:
 4708                 /* wait */
 4709                 break;
 4710         case 0x9c:
 4711                 x86emuOp_pushf_word(emu);
 4712                 break;
 4713         case 0x9d:
 4714                 x86emuOp_popf_word(emu);
 4715                 break;
 4716         case 0x9e:
 4717                 x86emuOp_sahf(emu);
 4718                 break;
 4719         case 0x9f:
 4720                 x86emuOp_lahf(emu);
 4721                 break;
 4722 
 4723         case 0xa0:
 4724                 x86emuOp_mov_AL_M_IMM(emu);
 4725                 break;
 4726         case 0xa1:
 4727                 x86emuOp_mov_AX_M_IMM(emu);
 4728                 break;
 4729         case 0xa2:
 4730                 x86emuOp_mov_M_AL_IMM(emu);
 4731                 break;
 4732         case 0xa3:
 4733                 x86emuOp_mov_M_AX_IMM(emu);
 4734                 break;
 4735         case 0xa4:
 4736                 x86emuOp_movs_byte(emu);
 4737                 break;
 4738         case 0xa5:
 4739                 x86emuOp_movs_word(emu);
 4740                 break;
 4741         case 0xa6:
 4742                 x86emuOp_cmps_byte(emu);
 4743                 break;
 4744         case 0xa7:
 4745                 x86emuOp_cmps_word(emu);
 4746                 break;
 4747 
 4748         case 0xa8:
 4749                 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
 4750                 break;
 4751         case 0xa9:
 4752                 x86emuOp_test_AX_IMM(emu);
 4753                 break;
 4754         case 0xaa:
 4755                 x86emuOp_stos_byte(emu);
 4756                 break;
 4757         case 0xab:
 4758                 x86emuOp_stos_word(emu);
 4759                 break;
 4760         case 0xac:
 4761                 x86emuOp_lods_byte(emu);
 4762                 break;
 4763         case 0xad:
 4764                 x86emuOp_lods_word(emu);
 4765                 break;
 4766         case 0xae:
 4767                 x86emuOp_scas_byte(emu);
 4768                 break;
 4769         case 0xaf:
 4770                 x86emuOp_scas_word(emu);
 4771                 break;
 4772 
 4773         case 0xb0:
 4774                 emu->x86.R_AL = fetch_byte_imm(emu);
 4775                 break;
 4776         case 0xb1:
 4777                 emu->x86.R_CL = fetch_byte_imm(emu);
 4778                 break;
 4779         case 0xb2:
 4780                 emu->x86.R_DL = fetch_byte_imm(emu);
 4781                 break;
 4782         case 0xb3:
 4783                 emu->x86.R_BL = fetch_byte_imm(emu);
 4784                 break;
 4785         case 0xb4:
 4786                 emu->x86.R_AH = fetch_byte_imm(emu);
 4787                 break;
 4788         case 0xb5:
 4789                 emu->x86.R_CH = fetch_byte_imm(emu);
 4790                 break;
 4791         case 0xb6:
 4792                 emu->x86.R_DH = fetch_byte_imm(emu);
 4793                 break;
 4794         case 0xb7:
 4795                 emu->x86.R_BH = fetch_byte_imm(emu);
 4796                 break;
 4797 
 4798         case 0xb8:
 4799                 x86emuOp_mov_word_AX_IMM(emu);
 4800                 break;
 4801         case 0xb9:
 4802                 x86emuOp_mov_word_CX_IMM(emu);
 4803                 break;
 4804         case 0xba:
 4805                 x86emuOp_mov_word_DX_IMM(emu);
 4806                 break;
 4807         case 0xbb:
 4808                 x86emuOp_mov_word_BX_IMM(emu);
 4809                 break;
 4810         case 0xbc:
 4811 
 4812                 x86emuOp_mov_word_SP_IMM(emu);
 4813                 break;
 4814         case 0xbd:
 4815                 x86emuOp_mov_word_BP_IMM(emu);
 4816                 break;
 4817         case 0xbe:
 4818                 x86emuOp_mov_word_SI_IMM(emu);
 4819                 break;
 4820         case 0xbf:
 4821                 x86emuOp_mov_word_DI_IMM(emu);
 4822                 break;
 4823 
 4824         case 0xc0:
 4825                 x86emuOp_opcC0_byte_RM_MEM(emu);
 4826                 break;
 4827         case 0xc1:
 4828                 x86emuOp_opcC1_word_RM_MEM(emu);
 4829                 break;
 4830         case 0xc2:
 4831                 x86emuOp_ret_near_IMM(emu);
 4832                 break;
 4833         case 0xc3:
 4834                 emu->x86.R_IP = pop_word(emu);
 4835                 break;
 4836         case 0xc4:
 4837                 common_load_far_pointer(emu, &emu->x86.R_ES);
 4838                 break;
 4839         case 0xc5:
 4840                 common_load_far_pointer(emu, &emu->x86.R_DS);
 4841                 break;
 4842         case 0xc6:
 4843                 x86emuOp_mov_byte_RM_IMM(emu);
 4844                 break;
 4845         case 0xc7:
 4846                 x86emuOp_mov_word_RM_IMM(emu);
 4847                 break;
 4848         case 0xc8:
 4849                 x86emuOp_enter(emu);
 4850                 break;
 4851         case 0xc9:
 4852                 x86emuOp_leave(emu);
 4853                 break;
 4854         case 0xca:
 4855                 x86emuOp_ret_far_IMM(emu);
 4856                 break;
 4857         case 0xcb:
 4858                 x86emuOp_ret_far(emu);
 4859                 break;
 4860         case 0xcc:
 4861                 x86emuOp_int3(emu);
 4862                 break;
 4863         case 0xcd:
 4864                 x86emuOp_int_IMM(emu);
 4865                 break;
 4866         case 0xce:
 4867                 x86emuOp_into(emu);
 4868                 break;
 4869         case 0xcf:
 4870                 x86emuOp_iret(emu);
 4871                 break;
 4872 
 4873         case 0xd0:
 4874                 x86emuOp_opcD0_byte_RM_1(emu);
 4875                 break;
 4876         case 0xd1:
 4877                 x86emuOp_opcD1_word_RM_1(emu);
 4878                 break;
 4879         case 0xd2:
 4880                 x86emuOp_opcD2_byte_RM_CL(emu);
 4881                 break;
 4882         case 0xd3:
 4883                 x86emuOp_opcD3_word_RM_CL(emu);
 4884                 break;
 4885         case 0xd4:
 4886                 x86emuOp_aam(emu);
 4887                 break;
 4888         case 0xd5:
 4889                 x86emuOp_aad(emu);
 4890                 break;
 4891         /* 0xd6 Undocumented SETALC instruction */
 4892         case 0xd7:
 4893                 x86emuOp_xlat(emu);
 4894                 break;
 4895         case 0xd8:
 4896                 x86emuOp_esc_coprocess_d8(emu);
 4897                 break;
 4898         case 0xd9:
 4899                 x86emuOp_esc_coprocess_d9(emu);
 4900                 break;
 4901         case 0xda:
 4902                 x86emuOp_esc_coprocess_da(emu);
 4903                 break;
 4904         case 0xdb:
 4905                 x86emuOp_esc_coprocess_db(emu);
 4906                 break;
 4907         case 0xdc:
 4908                 x86emuOp_esc_coprocess_dc(emu);
 4909                 break;
 4910         case 0xdd:
 4911                 x86emuOp_esc_coprocess_dd(emu);
 4912                 break;
 4913         case 0xde:
 4914                 x86emuOp_esc_coprocess_de(emu);
 4915                 break;
 4916         case 0xdf:
 4917                 x86emuOp_esc_coprocess_df(emu);
 4918                 break;
 4919 
 4920         case 0xe0:
 4921                 x86emuOp_loopne(emu);
 4922                 break;
 4923         case 0xe1:
 4924                 x86emuOp_loope(emu);
 4925                 break;
 4926         case 0xe2:
 4927                 x86emuOp_loop(emu);
 4928                 break;
 4929         case 0xe3:
 4930                 x86emuOp_jcxz(emu);
 4931                 break;
 4932         case 0xe4:
 4933                 x86emuOp_in_byte_AL_IMM(emu);
 4934                 break;
 4935         case 0xe5:
 4936                 x86emuOp_in_word_AX_IMM(emu);
 4937                 break;
 4938         case 0xe6:
 4939                 x86emuOp_out_byte_IMM_AL(emu);
 4940                 break;
 4941         case 0xe7:
 4942                 x86emuOp_out_word_IMM_AX(emu);
 4943                 break;
 4944 
 4945         case 0xe8:
 4946                 x86emuOp_call_near_IMM(emu);
 4947                 break;
 4948         case 0xe9:
 4949                 x86emuOp_jump_near_IMM(emu);
 4950                 break;
 4951         case 0xea:
 4952                 x86emuOp_jump_far_IMM(emu);
 4953                 break;
 4954         case 0xeb:
 4955                 x86emuOp_jump_byte_IMM(emu);
 4956                 break;
 4957         case 0xec:
 4958                 x86emuOp_in_byte_AL_DX(emu);
 4959                 break;
 4960         case 0xed:
 4961                 x86emuOp_in_word_AX_DX(emu);
 4962                 break;
 4963         case 0xee:
 4964                 x86emuOp_out_byte_DX_AL(emu);
 4965                 break;
 4966         case 0xef:
 4967                 x86emuOp_out_word_DX_AX(emu);
 4968                 break;
 4969 
 4970         case 0xf0:
 4971                 x86emuOp_lock(emu);
 4972                 break;
 4973         case 0xf2:
 4974                 emu->x86.mode |= SYSMODE_PREFIX_REPNE;
 4975                 break;
 4976         case 0xf3:
 4977                 emu->x86.mode |= SYSMODE_PREFIX_REPE;
 4978                 break;
 4979         case 0xf4:
 4980                 x86emu_halt_sys(emu);
 4981                 break;
 4982         case 0xf5:
 4983                 x86emuOp_cmc(emu);
 4984                 break;
 4985         case 0xf6:
 4986                 x86emuOp_opcF6_byte_RM(emu);
 4987                 break;
 4988         case 0xf7:
 4989                 x86emuOp_opcF7_word_RM(emu);
 4990                 break;
 4991 
 4992         case 0xf8:
 4993                 CLEAR_FLAG(F_CF);
 4994                 break;
 4995         case 0xf9:
 4996                 SET_FLAG(F_CF);
 4997                 break;
 4998         case 0xfa:
 4999                 CLEAR_FLAG(F_IF);
 5000                 break;
 5001         case 0xfb:
 5002                 SET_FLAG(F_IF);
 5003                 break;
 5004         case 0xfc:
 5005                 CLEAR_FLAG(F_DF);
 5006                 break;
 5007         case 0xfd:
 5008                 SET_FLAG(F_DF);
 5009                 break;
 5010         case 0xfe:
 5011                 x86emuOp_opcFE_byte_RM(emu);
 5012                 break;
 5013         case 0xff:
 5014                 x86emuOp_opcFF_word_RM(emu);
 5015                 break;
 5016         default:
 5017                 x86emu_halt_sys(emu);
 5018                 break;
 5019         }
 5020         if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
 5021             (op1 | 3) != 0x67)
 5022                 emu->x86.mode &= ~SYSMODE_CLRMASK;
 5023 }
 5024 
 5025 static void
 5026 common_jmp_long(struct x86emu *emu, int cond)
 5027 {
 5028         int16_t target;
 5029 
 5030         target = (int16_t) fetch_word_imm(emu);
 5031         target += (int16_t) emu->x86.R_IP;
 5032         if (cond)
 5033                 emu->x86.R_IP = (uint16_t) target;
 5034 }
 5035 
 5036 static void
 5037 common_set_byte(struct x86emu *emu, int cond)
 5038 {
 5039         uint32_t destoffset;
 5040         uint8_t *destreg, destval;
 5041 
 5042         fetch_decode_modrm(emu);
 5043         destval = cond ? 0x01 : 0x00;
 5044         if (emu->cur_mod != 3) {
 5045                 destoffset = decode_rl_address(emu);
 5046                 store_data_byte(emu, destoffset, destval);
 5047         } else {
 5048                 destreg = decode_rl_byte_register(emu);
 5049                 *destreg = destval;
 5050         }
 5051 }
 5052 
 5053 static void
 5054 common_bitstring32(struct x86emu *emu, int op)
 5055 {
 5056         int bit;
 5057         uint32_t srcval, *shiftreg, mask;
 5058 
 5059         fetch_decode_modrm(emu);
 5060         shiftreg = decode_rh_long_register(emu);
 5061         srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
 5062         bit = *shiftreg & 0x1F;
 5063         mask =  0x1 << bit;
 5064         CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
 5065 
 5066         switch (op) {
 5067         case 0:
 5068                 break;
 5069         case 1:
 5070                 write_back_long(emu, srcval | mask);
 5071                 break;
 5072         case 2:
 5073                 write_back_long(emu, srcval & ~mask);
 5074                 break;
 5075         case 3:
 5076                 write_back_long(emu, srcval ^ mask);
 5077                 break;
 5078         }
 5079 }
 5080 
 5081 static void
 5082 common_bitstring16(struct x86emu *emu, int op)
 5083 {
 5084         int bit;
 5085         uint16_t srcval, *shiftreg, mask;
 5086 
 5087         fetch_decode_modrm(emu);
 5088         shiftreg = decode_rh_word_register(emu);
 5089         srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
 5090         bit = *shiftreg & 0xF;
 5091         mask =  0x1 << bit;
 5092         CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
 5093 
 5094         switch (op) {
 5095         case 0:
 5096                 break;
 5097         case 1:
 5098                 write_back_word(emu, srcval | mask);
 5099                 break;
 5100         case 2:
 5101                 write_back_word(emu, srcval & ~mask);
 5102                 break;
 5103         case 3:
 5104                 write_back_word(emu, srcval ^ mask);
 5105                 break;
 5106         }
 5107 }
 5108 
 5109 static void
 5110 common_bitstring(struct x86emu *emu, int op)
 5111 {
 5112         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5113                 common_bitstring32(emu, op);
 5114         else
 5115                 common_bitstring16(emu, op);
 5116 }
 5117 
 5118 static void
 5119 common_bitsearch32(struct x86emu *emu, int diff)
 5120 {
 5121         uint32_t srcval, *dstreg;
 5122 
 5123         fetch_decode_modrm(emu);
 5124         dstreg = decode_rh_long_register(emu);
 5125         srcval = decode_and_fetch_long(emu);
 5126         CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
 5127         for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
 5128                 if ((srcval >> *dstreg) & 1)
 5129                         break;
 5130         }
 5131 }
 5132 
 5133 static void
 5134 common_bitsearch16(struct x86emu *emu, int diff)
 5135 {
 5136         uint16_t srcval, *dstreg;
 5137 
 5138         fetch_decode_modrm(emu);
 5139         dstreg = decode_rh_word_register(emu);
 5140         srcval = decode_and_fetch_word(emu);
 5141         CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
 5142         for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
 5143                 if ((srcval >> *dstreg) & 1)
 5144                         break;
 5145         }
 5146 }
 5147 
 5148 static void
 5149 common_bitsearch(struct x86emu *emu, int diff)
 5150 {
 5151         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5152                 common_bitsearch32(emu, diff);
 5153         else
 5154                 common_bitsearch16(emu, diff);
 5155 }
 5156 
 5157 static void
 5158 common_shift32(struct x86emu *emu, int shift_left, int use_cl)
 5159 {
 5160         uint8_t shift;
 5161         uint32_t destval, *shiftreg;
 5162 
 5163         fetch_decode_modrm(emu);
 5164         shiftreg = decode_rh_long_register(emu);
 5165         if (use_cl) {
 5166                 destval = decode_and_fetch_long(emu);
 5167                 shift = emu->x86.R_CL;
 5168         } else {
 5169                 destval = decode_and_fetch_long_imm8(emu, &shift);
 5170         }
 5171         if (shift_left)
 5172                 destval = shld_long(emu, destval, *shiftreg, shift);
 5173         else
 5174                 destval = shrd_long(emu, destval, *shiftreg, shift);
 5175         write_back_long(emu, destval);
 5176 }
 5177 
 5178 static void
 5179 common_shift16(struct x86emu *emu, int shift_left, int use_cl)
 5180 {
 5181         uint8_t shift;
 5182         uint16_t destval, *shiftreg;
 5183 
 5184         fetch_decode_modrm(emu);
 5185         shiftreg = decode_rh_word_register(emu);
 5186         if (use_cl) {
 5187                 destval = decode_and_fetch_word(emu);
 5188                 shift = emu->x86.R_CL;
 5189         } else {
 5190                 destval = decode_and_fetch_word_imm8(emu, &shift);
 5191         }
 5192         if (shift_left)
 5193                 destval = shld_word(emu, destval, *shiftreg, shift);
 5194         else
 5195                 destval = shrd_word(emu, destval, *shiftreg, shift);
 5196         write_back_word(emu, destval);
 5197 }
 5198 
 5199 static void
 5200 common_shift(struct x86emu *emu, int shift_left, int use_cl)
 5201 {
 5202         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5203                 common_shift32(emu, shift_left, use_cl);
 5204         else
 5205                 common_shift16(emu, shift_left, use_cl);
 5206 }
 5207 
 5208 /*
 5209  * Implementation
 5210  */
 5211 #define xorl(a,b)   ((a) && !(b)) || (!(a) && (b))
 5212 
 5213 
 5214 /*
 5215  * REMARKS:
 5216  * Handles opcode 0x0f,0x31
 5217  */
 5218 static void
 5219 x86emuOp2_rdtsc(struct x86emu *emu)
 5220 {
 5221         emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
 5222         emu->x86.R_EDX = emu->cur_cycles >> 32;
 5223 }
 5224 
 5225 /*
 5226  * REMARKS:
 5227  * Handles opcode 0x0f,0xa0
 5228  */
 5229 static void
 5230 x86emuOp2_push_FS(struct x86emu *emu)
 5231 {
 5232         push_word(emu, emu->x86.R_FS);
 5233 }
 5234 
 5235 /*
 5236  * REMARKS:
 5237  * Handles opcode 0x0f,0xa1
 5238  */
 5239 static void
 5240 x86emuOp2_pop_FS(struct x86emu *emu)
 5241 {
 5242         emu->x86.R_FS = pop_word(emu);
 5243 }
 5244 
 5245 /*
 5246  * REMARKS:
 5247  * Handles opcode 0x0f,0xa1
 5248  */
 5249 #if defined(__i386__) || defined(__amd64__)
 5250 static void
 5251 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
 5252 {
 5253         __asm__ volatile("cpuid"
 5254                              : "=a" (*a), "=b" (*b),
 5255                                "=c" (*c), "=d" (*d)
 5256                              : "a" (*a), "c" (*c)
 5257                              : "cc");
 5258 }
 5259 #endif
 5260 static void
 5261 x86emuOp2_cpuid(struct x86emu *emu)
 5262 {
 5263 #if defined(__i386__) || defined(__amd64__)
 5264         hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
 5265             &emu->x86.R_EDX);
 5266 #endif
 5267         switch (emu->x86.R_EAX) {
 5268         case 0:
 5269                 emu->x86.R_EAX = 1;
 5270 #if !defined(__i386__) && !defined(__amd64__)
 5271                 /* "GenuineIntel" */
 5272                 emu->x86.R_EBX = 0x756e6547;
 5273                 emu->x86.R_EDX = 0x49656e69;
 5274                 emu->x86.R_ECX = 0x6c65746e;
 5275 #endif
 5276                 break;
 5277         case 1:
 5278 #if !defined(__i386__) && !defined(__amd64__)
 5279                 emu->x86.R_EAX = 0x00000480;
 5280                 emu->x86.R_EBX = emu->x86.R_ECX = 0;
 5281                 emu->x86.R_EDX = 0x00000002;
 5282 #else
 5283                 emu->x86.R_EDX &= 0x00000012;
 5284 #endif
 5285                 break;
 5286         default:
 5287                 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
 5288                     emu->x86.R_EDX = 0;
 5289                 break;
 5290         }
 5291 }
 5292 
 5293 /*
 5294  * REMARKS:
 5295  * Handles opcode 0x0f,0xa3
 5296  */
 5297 static void
 5298 x86emuOp2_bt_R(struct x86emu *emu)
 5299 {
 5300         common_bitstring(emu, 0);
 5301 }
 5302 
 5303 /*
 5304  * REMARKS:
 5305  * Handles opcode 0x0f,0xa4
 5306  */
 5307 static void
 5308 x86emuOp2_shld_IMM(struct x86emu *emu)
 5309 {
 5310         common_shift(emu, 1, 0);
 5311 }
 5312 
 5313 /*
 5314  * REMARKS:
 5315  * Handles opcode 0x0f,0xa5
 5316  */
 5317 static void
 5318 x86emuOp2_shld_CL(struct x86emu *emu)
 5319 {
 5320         common_shift(emu, 1, 1);
 5321 }
 5322 
 5323 /*
 5324  * REMARKS:
 5325  * Handles opcode 0x0f,0xa8
 5326  */
 5327 static void
 5328 x86emuOp2_push_GS(struct x86emu *emu)
 5329 {
 5330         push_word(emu, emu->x86.R_GS);
 5331 }
 5332 
 5333 /*
 5334  * REMARKS:
 5335  * Handles opcode 0x0f,0xa9
 5336  */
 5337 static void
 5338 x86emuOp2_pop_GS(struct x86emu *emu)
 5339 {
 5340         emu->x86.R_GS = pop_word(emu);
 5341 }
 5342 
 5343 /*
 5344  * REMARKS:
 5345  * Handles opcode 0x0f,0xab
 5346  */
 5347 static void
 5348 x86emuOp2_bts_R(struct x86emu *emu)
 5349 {
 5350         common_bitstring(emu, 1);
 5351 }
 5352 
 5353 /*
 5354  * REMARKS:
 5355  * Handles opcode 0x0f,0xac
 5356  */
 5357 static void
 5358 x86emuOp2_shrd_IMM(struct x86emu *emu)
 5359 {
 5360         common_shift(emu, 0, 0);
 5361 }
 5362 
 5363 /*
 5364  * REMARKS:
 5365  * Handles opcode 0x0f,0xad
 5366  */
 5367 static void
 5368 x86emuOp2_shrd_CL(struct x86emu *emu)
 5369 {
 5370         common_shift(emu, 0, 1);
 5371 }
 5372 
 5373 /*
 5374  * REMARKS:
 5375  * Handles opcode 0x0f,0xaf
 5376  */
 5377 static void
 5378 x86emuOp2_32_imul_R_RM(struct x86emu *emu)
 5379 {
 5380         uint32_t *destreg, srcval;
 5381         uint64_t res;
 5382 
 5383         fetch_decode_modrm(emu);
 5384         destreg = decode_rh_long_register(emu);
 5385         srcval = decode_and_fetch_long(emu);
 5386         res = (int32_t) *destreg * (int32_t)srcval;
 5387         if (res > 0xffffffff) {
 5388                 SET_FLAG(F_CF);
 5389                 SET_FLAG(F_OF);
 5390         } else {
 5391                 CLEAR_FLAG(F_CF);
 5392                 CLEAR_FLAG(F_OF);
 5393         }
 5394         *destreg = (uint32_t) res;
 5395 }
 5396 
 5397 static void
 5398 x86emuOp2_16_imul_R_RM(struct x86emu *emu)
 5399 {
 5400         uint16_t *destreg, srcval;
 5401         uint32_t res;
 5402 
 5403         fetch_decode_modrm(emu);
 5404         destreg = decode_rh_word_register(emu);
 5405         srcval = decode_and_fetch_word(emu);
 5406         res = (int16_t) * destreg * (int16_t)srcval;
 5407         if (res > 0xFFFF) {
 5408                 SET_FLAG(F_CF);
 5409                 SET_FLAG(F_OF);
 5410         } else {
 5411                 CLEAR_FLAG(F_CF);
 5412                 CLEAR_FLAG(F_OF);
 5413         }
 5414         *destreg = (uint16_t) res;
 5415 }
 5416 
 5417 static void
 5418 x86emuOp2_imul_R_RM(struct x86emu *emu)
 5419 {
 5420         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5421                 x86emuOp2_32_imul_R_RM(emu);
 5422         else
 5423                 x86emuOp2_16_imul_R_RM(emu);
 5424 }
 5425 
 5426 /*
 5427  * REMARKS:
 5428  * Handles opcode 0x0f,0xb2
 5429  */
 5430 static void
 5431 x86emuOp2_lss_R_IMM(struct x86emu *emu)
 5432 {
 5433         common_load_far_pointer(emu, &emu->x86.R_SS);
 5434 }
 5435 
 5436 /*
 5437  * REMARKS:
 5438  * Handles opcode 0x0f,0xb3
 5439  */
 5440 static void
 5441 x86emuOp2_btr_R(struct x86emu *emu)
 5442 {
 5443         common_bitstring(emu, 2);
 5444 }
 5445 
 5446 /*
 5447  * REMARKS:
 5448  * Handles opcode 0x0f,0xb4
 5449  */
 5450 static void
 5451 x86emuOp2_lfs_R_IMM(struct x86emu *emu)
 5452 {
 5453         common_load_far_pointer(emu, &emu->x86.R_FS);
 5454 }
 5455 
 5456 /*
 5457  * REMARKS:
 5458  * Handles opcode 0x0f,0xb5
 5459  */
 5460 static void
 5461 x86emuOp2_lgs_R_IMM(struct x86emu *emu)
 5462 {
 5463         common_load_far_pointer(emu, &emu->x86.R_GS);
 5464 }
 5465 
 5466 /*
 5467  * REMARKS:
 5468  * Handles opcode 0x0f,0xb6
 5469  */
 5470 static void
 5471 x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
 5472 {
 5473         uint32_t *destreg;
 5474 
 5475         fetch_decode_modrm(emu);
 5476         destreg = decode_rh_long_register(emu);
 5477         *destreg = decode_and_fetch_byte(emu);
 5478 }
 5479 
 5480 static void
 5481 x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
 5482 {
 5483         uint16_t *destreg;
 5484 
 5485         fetch_decode_modrm(emu);
 5486         destreg = decode_rh_word_register(emu);
 5487         *destreg = decode_and_fetch_byte(emu);
 5488 }
 5489 
 5490 static void
 5491 x86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
 5492 {
 5493         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5494                 x86emuOp2_32_movzx_byte_R_RM(emu);
 5495         else
 5496                 x86emuOp2_16_movzx_byte_R_RM(emu);
 5497 }
 5498 
 5499 /*
 5500  * REMARKS:
 5501  * Handles opcode 0x0f,0xb7
 5502  */
 5503 static void
 5504 x86emuOp2_movzx_word_R_RM(struct x86emu *emu)
 5505 {
 5506         uint32_t *destreg;
 5507 
 5508         fetch_decode_modrm(emu);
 5509         destreg = decode_rh_long_register(emu);
 5510         *destreg = decode_and_fetch_word(emu);
 5511 }
 5512 
 5513 /*
 5514  * REMARKS:
 5515  * Handles opcode 0x0f,0xba
 5516  */
 5517 static void
 5518 x86emuOp2_32_btX_I(struct x86emu *emu)
 5519 {
 5520         int bit;
 5521         uint32_t srcval, mask;
 5522         uint8_t shift;
 5523 
 5524         fetch_decode_modrm(emu);
 5525         if (emu->cur_rh < 4)
 5526                 x86emu_halt_sys(emu);
 5527 
 5528         srcval = decode_and_fetch_long_imm8(emu, &shift);
 5529         bit = shift & 0x1F;
 5530         mask = (0x1 << bit);
 5531 
 5532         switch (emu->cur_rh) {
 5533         case 5:
 5534                 write_back_long(emu, srcval | mask);
 5535                 break;
 5536         case 6:
 5537                 write_back_long(emu, srcval & ~mask);
 5538                 break;
 5539         case 7:
 5540                 write_back_long(emu, srcval ^ mask);
 5541                 break;
 5542         }
 5543         CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
 5544 }
 5545 
 5546 static void
 5547 x86emuOp2_16_btX_I(struct x86emu *emu)
 5548 {
 5549         int bit;
 5550 
 5551         uint16_t srcval, mask;
 5552         uint8_t shift;
 5553 
 5554         fetch_decode_modrm(emu);
 5555         if (emu->cur_rh < 4)
 5556                 x86emu_halt_sys(emu);
 5557 
 5558         srcval = decode_and_fetch_word_imm8(emu, &shift);
 5559         bit = shift & 0xF;
 5560         mask = (0x1 << bit);
 5561         switch (emu->cur_rh) {
 5562         case 5:
 5563                 write_back_word(emu, srcval | mask);
 5564                 break;
 5565         case 6:
 5566                 write_back_word(emu, srcval & ~mask);
 5567                 break;
 5568         case 7:
 5569                 write_back_word(emu, srcval ^ mask);
 5570                 break;
 5571         }
 5572         CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
 5573 }
 5574 
 5575 static void
 5576 x86emuOp2_btX_I(struct x86emu *emu)
 5577 {
 5578         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5579                 x86emuOp2_32_btX_I(emu);
 5580         else
 5581                 x86emuOp2_16_btX_I(emu);
 5582 }
 5583 
 5584 /*
 5585  * REMARKS:
 5586  * Handles opcode 0x0f,0xbb
 5587  */
 5588 static void
 5589 x86emuOp2_btc_R(struct x86emu *emu)
 5590 {
 5591         common_bitstring(emu, 3);
 5592 }
 5593 
 5594 /*
 5595  * REMARKS:
 5596  * Handles opcode 0x0f,0xbc
 5597  */
 5598 static void
 5599 x86emuOp2_bsf(struct x86emu *emu)
 5600 {
 5601         common_bitsearch(emu, +1);
 5602 }
 5603 
 5604 /*
 5605  * REMARKS:
 5606  * Handles opcode 0x0f,0xbd
 5607  */
 5608 static void
 5609 x86emuOp2_bsr(struct x86emu *emu)
 5610 {
 5611         common_bitsearch(emu, -1);
 5612 }
 5613 
 5614 /*
 5615  * REMARKS:
 5616  * Handles opcode 0x0f,0xbe
 5617  */
 5618 static void
 5619 x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
 5620 {
 5621         uint32_t *destreg;
 5622 
 5623         fetch_decode_modrm(emu);
 5624         destreg = decode_rh_long_register(emu);
 5625         *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
 5626 }
 5627 
 5628 static void
 5629 x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
 5630 {
 5631         uint16_t *destreg;
 5632 
 5633         fetch_decode_modrm(emu);
 5634         destreg = decode_rh_word_register(emu);
 5635         *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
 5636 }
 5637 
 5638 static void
 5639 x86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
 5640 {
 5641         if (emu->x86.mode & SYSMODE_PREFIX_DATA)
 5642                 x86emuOp2_32_movsx_byte_R_RM(emu);
 5643         else
 5644                 x86emuOp2_16_movsx_byte_R_RM(emu);
 5645 }
 5646 
 5647 /*
 5648  * REMARKS:
 5649  * Handles opcode 0x0f,0xbf
 5650  */
 5651 static void
 5652 x86emuOp2_movsx_word_R_RM(struct x86emu *emu)
 5653 {
 5654         uint32_t *destreg;
 5655 
 5656         fetch_decode_modrm(emu);
 5657         destreg = decode_rh_long_register(emu);
 5658         *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
 5659 }
 5660 
 5661 static void
 5662 x86emu_exec_two_byte(struct x86emu * emu)
 5663 {
 5664         uint8_t op2;
 5665 
 5666         op2 = fetch_byte_imm(emu);
 5667 
 5668         switch (op2) {
 5669         /* 0x00 Group F (ring 0 PM)      */
 5670         /* 0x01 Group G (ring 0 PM)      */
 5671         /* 0x02 lar (ring 0 PM)          */
 5672         /* 0x03 lsl (ring 0 PM)          */
 5673         /* 0x05 loadall (undocumented)   */
 5674         /* 0x06 clts (ring 0 PM)         */
 5675         /* 0x07 loadall (undocumented)   */
 5676         /* 0x08 invd (ring 0 PM)         */
 5677         /* 0x09 wbinvd (ring 0 PM)       */
 5678 
 5679         /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
 5680         /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
 5681         /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
 5682         /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
 5683         /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
 5684         /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
 5685 
 5686         case 0x31:
 5687                 x86emuOp2_rdtsc(emu);
 5688                 break;
 5689 
 5690         case 0x80:
 5691                 common_jmp_long(emu, ACCESS_FLAG(F_OF));
 5692                 break;
 5693         case 0x81:
 5694                 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
 5695                 break;
 5696         case 0x82:
 5697                 common_jmp_long(emu, ACCESS_FLAG(F_CF));
 5698                 break;
 5699         case 0x83:
 5700                 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
 5701                 break;
 5702         case 0x84:
 5703                 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
 5704                 break;
 5705         case 0x85:
 5706                 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
 5707                 break;
 5708         case 0x86:
 5709                 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
 5710                 break;
 5711         case 0x87:
 5712                 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
 5713                 break;
 5714         case 0x88:
 5715                 common_jmp_long(emu, ACCESS_FLAG(F_SF));
 5716                 break;
 5717         case 0x89:
 5718                 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
 5719                 break;
 5720         case 0x8a:
 5721                 common_jmp_long(emu, ACCESS_FLAG(F_PF));
 5722                 break;
 5723         case 0x8b:
 5724                 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
 5725                 break;
 5726         case 0x8c:
 5727                 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
 5728                     ACCESS_FLAG(F_OF)));
 5729                 break;
 5730         case 0x8d:
 5731                 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
 5732                     ACCESS_FLAG(F_OF))));
 5733                 break;
 5734         case 0x8e:
 5735                 common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
 5736                     || ACCESS_FLAG(F_ZF)));
 5737                 break;
 5738         case 0x8f:
 5739                 common_jmp_long(emu, 
 5740                     !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
 5741                     ACCESS_FLAG(F_ZF)));
 5742                 break;
 5743 
 5744         case 0x90:
 5745                 common_set_byte(emu, ACCESS_FLAG(F_OF));
 5746                 break;
 5747         case 0x91:
 5748                 common_set_byte(emu, !ACCESS_FLAG(F_OF));
 5749                 break;
 5750         case 0x92:
 5751                 common_set_byte(emu, ACCESS_FLAG(F_CF));
 5752                 break;
 5753         case 0x93:
 5754                 common_set_byte(emu, !ACCESS_FLAG(F_CF));
 5755                 break;
 5756         case 0x94:
 5757                 common_set_byte(emu, ACCESS_FLAG(F_ZF));
 5758                 break;
 5759         case 0x95:
 5760                 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
 5761                 break;
 5762         case 0x96:
 5763                 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
 5764                 break;
 5765         case 0x97:
 5766                 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
 5767                 break;
 5768         case 0x98:
 5769                 common_set_byte(emu, ACCESS_FLAG(F_SF));
 5770                 break;
 5771         case 0x99:
 5772                 common_set_byte(emu, !ACCESS_FLAG(F_SF));
 5773                 break;
 5774         case 0x9a:
 5775                 common_set_byte(emu, ACCESS_FLAG(F_PF));
 5776                 break;
 5777         case 0x9b:
 5778                 common_set_byte(emu, !ACCESS_FLAG(F_PF));
 5779                 break;
 5780         case 0x9c:
 5781                 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
 5782                     ACCESS_FLAG(F_OF)));
 5783                 break;
 5784         case 0x9d:
 5785                 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
 5786                     ACCESS_FLAG(F_OF)));
 5787                 break;
 5788         case 0x9e:
 5789                 common_set_byte(emu,
 5790                     (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
 5791                     ACCESS_FLAG(F_ZF)));
 5792                 break;
 5793         case 0x9f:
 5794                 common_set_byte(emu,
 5795                     !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
 5796                     ACCESS_FLAG(F_ZF)));
 5797                 break;
 5798 
 5799         case 0xa0:
 5800                 x86emuOp2_push_FS(emu);
 5801                 break;
 5802         case 0xa1:
 5803                 x86emuOp2_pop_FS(emu);
 5804                 break;
 5805         case 0xa2:
 5806                 x86emuOp2_cpuid(emu);
 5807                 break;
 5808         case 0xa3:
 5809                 x86emuOp2_bt_R(emu);
 5810                 break;
 5811         case 0xa4:
 5812                 x86emuOp2_shld_IMM(emu);
 5813                 break;
 5814         case 0xa5:
 5815                 x86emuOp2_shld_CL(emu);
 5816                 break;
 5817         case 0xa8:
 5818                 x86emuOp2_push_GS(emu);
 5819                 break;
 5820         case 0xa9:
 5821                 x86emuOp2_pop_GS(emu);
 5822                 break;
 5823         case 0xab:
 5824                 x86emuOp2_bts_R(emu);
 5825                 break;
 5826         case 0xac:
 5827                 x86emuOp2_shrd_IMM(emu);
 5828                 break;
 5829         case 0xad:
 5830                 x86emuOp2_shrd_CL(emu);
 5831                 break;
 5832         case 0xaf:
 5833                 x86emuOp2_imul_R_RM(emu);
 5834                 break;
 5835 
 5836         /* 0xb0 TODO: cmpxchg */
 5837         /* 0xb1 TODO: cmpxchg */
 5838         case 0xb2:
 5839                 x86emuOp2_lss_R_IMM(emu);
 5840                 break;
 5841         case 0xb3:
 5842                 x86emuOp2_btr_R(emu);
 5843                 break;
 5844         case 0xb4:
 5845                 x86emuOp2_lfs_R_IMM(emu);
 5846                 break;
 5847         case 0xb5:
 5848                 x86emuOp2_lgs_R_IMM(emu);
 5849                 break;
 5850         case 0xb6:
 5851                 x86emuOp2_movzx_byte_R_RM(emu);
 5852                 break;
 5853         case 0xb7:
 5854                 x86emuOp2_movzx_word_R_RM(emu);
 5855                 break;
 5856         case 0xba:
 5857                 x86emuOp2_btX_I(emu);
 5858                 break;
 5859         case 0xbb:
 5860                 x86emuOp2_btc_R(emu);
 5861                 break;
 5862         case 0xbc:
 5863                 x86emuOp2_bsf(emu);
 5864                 break;
 5865         case 0xbd:
 5866                 x86emuOp2_bsr(emu);
 5867                 break;
 5868         case 0xbe:
 5869                 x86emuOp2_movsx_byte_R_RM(emu);
 5870                 break;
 5871         case 0xbf:
 5872                 x86emuOp2_movsx_word_R_RM(emu);
 5873                 break;
 5874 
 5875         /* 0xc0 TODO: xadd */
 5876         /* 0xc1 TODO: xadd */
 5877         /* 0xc8 TODO: bswap */
 5878         /* 0xc9 TODO: bswap */
 5879         /* 0xca TODO: bswap */
 5880         /* 0xcb TODO: bswap */
 5881         /* 0xcc TODO: bswap */
 5882         /* 0xcd TODO: bswap */
 5883         /* 0xce TODO: bswap */
 5884         /* 0xcf TODO: bswap */
 5885 
 5886         default:
 5887                 x86emu_halt_sys(emu);
 5888                 break;
 5889         }
 5890 }
 5891 
 5892 /*
 5893  * Carry Chain Calculation
 5894  *
 5895  * This represents a somewhat expensive calculation which is
 5896  * apparently required to emulate the setting of the OF and AF flag.
 5897  * The latter is not so important, but the former is.  The overflow
 5898  * flag is the XOR of the top two bits of the carry chain for an
 5899  * addition (similar for subtraction).  Since we do not want to
 5900  * simulate the addition in a bitwise manner, we try to calculate the
 5901  * carry chain given the two operands and the result.
 5902  *
 5903  * So, given the following table, which represents the addition of two
 5904  * bits, we can derive a formula for the carry chain.
 5905  *
 5906  * a   b   cin   r     cout
 5907  * 0   0   0     0     0
 5908  * 0   0   1     1     0
 5909  * 0   1   0     1     0
 5910  * 0   1   1     0     1
 5911  * 1   0   0     1     0
 5912  * 1   0   1     0     1
 5913  * 1   1   0     0     1
 5914  * 1   1   1     1     1
 5915  *
 5916  * Construction of table for cout:
 5917  *
 5918  * ab
 5919  * r  \  00   01   11  10
 5920  * |------------------
 5921  * 0  |   0    1    1   1
 5922  * 1  |   0    0    1   0
 5923  *
 5924  * By inspection, one gets:  cc = ab +  r'(a + b)
 5925  *
 5926  * That represents alot of operations, but NO CHOICE....
 5927  *
 5928  * Borrow Chain Calculation.
 5929  *
 5930  * The following table represents the subtraction of two bits, from
 5931  * which we can derive a formula for the borrow chain.
 5932  *
 5933  * a   b   bin   r     bout
 5934  * 0   0   0     0     0
 5935  * 0   0   1     1     1
 5936  * 0   1   0     1     1
 5937  * 0   1   1     0     1
 5938  * 1   0   0     1     0
 5939  * 1   0   1     0     0
 5940  * 1   1   0     0     0
 5941  * 1   1   1     1     1
 5942  *
 5943  * Construction of table for cout:
 5944  *
 5945  * ab
 5946  * r  \  00   01   11  10
 5947  * |------------------
 5948  * 0  |   0    1    0   0
 5949  * 1  |   1    1    1   0
 5950  *
 5951  * By inspection, one gets:  bc = a'b +  r(a' + b)
 5952  *
 5953  */
 5954 
 5955 /*
 5956  * Global Variables
 5957  */
 5958 
 5959 static uint32_t x86emu_parity_tab[8] =
 5960 {
 5961         0x96696996,
 5962         0x69969669,
 5963         0x69969669,
 5964         0x96696996,
 5965         0x69969669,
 5966         0x96696996,
 5967         0x96696996,
 5968         0x69969669,
 5969 };
 5970 #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
 5971 #define XOR2(x)         (((x) ^ ((x)>>1)) & 0x1)
 5972 
 5973 
 5974 /*
 5975  * REMARKS:
 5976  * Implements the AAA instruction and side effects.
 5977  */
 5978 static uint16_t 
 5979 aaa_word(struct x86emu *emu, uint16_t d)
 5980 {
 5981         uint16_t res;
 5982         if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
 5983                 d += 0x6;
 5984                 d += 0x100;
 5985                 SET_FLAG(F_AF);
 5986                 SET_FLAG(F_CF);
 5987         } else {
 5988                 CLEAR_FLAG(F_CF);
 5989                 CLEAR_FLAG(F_AF);
 5990         }
 5991         res = (uint16_t) (d & 0xFF0F);
 5992         CLEAR_FLAG(F_SF);
 5993         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 5994         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 5995         return res;
 5996 }
 5997 
 5998 /*
 5999  * REMARKS:
 6000  * Implements the AAA instruction and side effects.
 6001  */
 6002 static uint16_t 
 6003 aas_word(struct x86emu *emu, uint16_t d)
 6004 {
 6005         uint16_t res;
 6006         if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
 6007                 d -= 0x6;
 6008                 d -= 0x100;
 6009                 SET_FLAG(F_AF);
 6010                 SET_FLAG(F_CF);
 6011         } else {
 6012                 CLEAR_FLAG(F_CF);
 6013                 CLEAR_FLAG(F_AF);
 6014         }
 6015         res = (uint16_t) (d & 0xFF0F);
 6016         CLEAR_FLAG(F_SF);
 6017         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6018         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6019         return res;
 6020 }
 6021 
 6022 /*
 6023  * REMARKS:
 6024  * Implements the AAD instruction and side effects.
 6025  */
 6026 static uint16_t 
 6027 aad_word(struct x86emu *emu, uint16_t d)
 6028 {
 6029         uint16_t l;
 6030         uint8_t hb, lb;
 6031 
 6032         hb = (uint8_t) ((d >> 8) & 0xff);
 6033         lb = (uint8_t) ((d & 0xff));
 6034         l = (uint16_t) ((lb + 10 * hb) & 0xFF);
 6035 
 6036         CLEAR_FLAG(F_CF);
 6037         CLEAR_FLAG(F_AF);
 6038         CLEAR_FLAG(F_OF);
 6039         CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
 6040         CONDITIONAL_SET_FLAG(l == 0, F_ZF);
 6041         CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
 6042         return l;
 6043 }
 6044 
 6045 /*
 6046  * REMARKS:
 6047  * Implements the AAM instruction and side effects.
 6048  */
 6049 static uint16_t 
 6050 aam_word(struct x86emu *emu, uint8_t d)
 6051 {
 6052         uint16_t h, l;
 6053 
 6054         h = (uint16_t) (d / 10);
 6055         l = (uint16_t) (d % 10);
 6056         l |= (uint16_t) (h << 8);
 6057 
 6058         CLEAR_FLAG(F_CF);
 6059         CLEAR_FLAG(F_AF);
 6060         CLEAR_FLAG(F_OF);
 6061         CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
 6062         CONDITIONAL_SET_FLAG(l == 0, F_ZF);
 6063         CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
 6064         return l;
 6065 }
 6066 
 6067 /*
 6068  * REMARKS:
 6069  * Implements the ADC instruction and side effects.
 6070  */
 6071 static uint8_t 
 6072 adc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6073 {
 6074         uint32_t res;   /* all operands in native machine order */
 6075         uint32_t cc;
 6076 
 6077         if (ACCESS_FLAG(F_CF))
 6078                 res = 1 + d + s;
 6079         else
 6080                 res = d + s;
 6081 
 6082         CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
 6083         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 6084         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6085         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6086 
 6087         /* calculate the carry chain  SEE NOTE AT TOP. */
 6088         cc = (s & d) | ((~res) & (s | d));
 6089         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
 6090         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6091         return (uint8_t) res;
 6092 }
 6093 
 6094 /*
 6095  * REMARKS:
 6096  * Implements the ADC instruction and side effects.
 6097  */
 6098 static uint16_t 
 6099 adc_word(struct x86emu *emu, uint16_t d, uint16_t s)
 6100 {
 6101         uint32_t res;   /* all operands in native machine order */
 6102         uint32_t cc;
 6103 
 6104         if (ACCESS_FLAG(F_CF))
 6105                 res = 1 + d + s;
 6106         else
 6107                 res = d + s;
 6108 
 6109         CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
 6110         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 6111         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6112         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6113 
 6114         /* calculate the carry chain  SEE NOTE AT TOP. */
 6115         cc = (s & d) | ((~res) & (s | d));
 6116         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
 6117         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6118         return (uint16_t) res;
 6119 }
 6120 
 6121 /*
 6122  * REMARKS:
 6123  * Implements the ADC instruction and side effects.
 6124  */
 6125 static uint32_t 
 6126 adc_long(struct x86emu *emu, uint32_t d, uint32_t s)
 6127 {
 6128         uint32_t lo;    /* all operands in native machine order */
 6129         uint32_t hi;
 6130         uint32_t res;
 6131         uint32_t cc;
 6132 
 6133         if (ACCESS_FLAG(F_CF)) {
 6134                 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
 6135                 res = 1 + d + s;
 6136         } else {
 6137                 lo = (d & 0xFFFF) + (s & 0xFFFF);
 6138                 res = d + s;
 6139         }
 6140         hi = (lo >> 16) + (d >> 16) + (s >> 16);
 6141 
 6142         CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
 6143         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 6144         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6145         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6146 
 6147         /* calculate the carry chain  SEE NOTE AT TOP. */
 6148         cc = (s & d) | ((~res) & (s | d));
 6149         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
 6150         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6151         return res;
 6152 }
 6153 
 6154 /*
 6155  * REMARKS:
 6156  * Implements the ADD instruction and side effects.
 6157  */
 6158 static uint8_t 
 6159 add_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6160 {
 6161         uint32_t res;   /* all operands in native machine order */
 6162         uint32_t cc;
 6163 
 6164         res = d + s;
 6165         CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
 6166         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 6167         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6168         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6169 
 6170         /* calculate the carry chain  SEE NOTE AT TOP. */
 6171         cc = (s & d) | ((~res) & (s | d));
 6172         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
 6173         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6174         return (uint8_t) res;
 6175 }
 6176 
 6177 /*
 6178  * REMARKS:
 6179  * Implements the ADD instruction and side effects.
 6180  */
 6181 static uint16_t 
 6182 add_word(struct x86emu *emu, uint16_t d, uint16_t s)
 6183 {
 6184         uint32_t res;   /* all operands in native machine order */
 6185         uint32_t cc;
 6186 
 6187         res = d + s;
 6188         CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
 6189         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 6190         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6191         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6192 
 6193         /* calculate the carry chain  SEE NOTE AT TOP. */
 6194         cc = (s & d) | ((~res) & (s | d));
 6195         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
 6196         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6197         return (uint16_t) res;
 6198 }
 6199 
 6200 /*
 6201  * REMARKS:
 6202  * Implements the ADD instruction and side effects.
 6203  */
 6204 static uint32_t 
 6205 add_long(struct x86emu *emu, uint32_t d, uint32_t s)
 6206 {
 6207         uint32_t lo;    /* all operands in native machine order */
 6208         uint32_t hi;
 6209         uint32_t res;
 6210         uint32_t cc;
 6211 
 6212         lo = (d & 0xFFFF) + (s & 0xFFFF);
 6213         res = d + s;
 6214         hi = (lo >> 16) + (d >> 16) + (s >> 16);
 6215 
 6216         CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
 6217         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 6218         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6219         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6220 
 6221         /* calculate the carry chain  SEE NOTE AT TOP. */
 6222         cc = (s & d) | ((~res) & (s | d));
 6223         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
 6224         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6225 
 6226         return res;
 6227 }
 6228 
 6229 /*
 6230  * REMARKS:
 6231  * Implements the AND instruction and side effects.
 6232  */
 6233 static uint8_t 
 6234 and_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6235 {
 6236         uint8_t res;    /* all operands in native machine order */
 6237 
 6238         res = d & s;
 6239 
 6240         /* set the flags  */
 6241         CLEAR_FLAG(F_OF);
 6242         CLEAR_FLAG(F_CF);
 6243         CLEAR_FLAG(F_AF);
 6244         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6245         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6246         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
 6247         return res;
 6248 }
 6249 
 6250 /*
 6251  * REMARKS:
 6252  * Implements the AND instruction and side effects.
 6253  */
 6254 static uint16_t 
 6255 and_word(struct x86emu *emu, uint16_t d, uint16_t s)
 6256 {
 6257         uint16_t res;   /* all operands in native machine order */
 6258 
 6259         res = d & s;
 6260 
 6261         /* set the flags  */
 6262         CLEAR_FLAG(F_OF);
 6263         CLEAR_FLAG(F_CF);
 6264         CLEAR_FLAG(F_AF);
 6265         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6266         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6267         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6268         return res;
 6269 }
 6270 
 6271 /*
 6272  * REMARKS:
 6273  * Implements the AND instruction and side effects.
 6274  */
 6275 static uint32_t 
 6276 and_long(struct x86emu *emu, uint32_t d, uint32_t s)
 6277 {
 6278         uint32_t res;   /* all operands in native machine order */
 6279 
 6280         res = d & s;
 6281 
 6282         /* set the flags  */
 6283         CLEAR_FLAG(F_OF);
 6284         CLEAR_FLAG(F_CF);
 6285         CLEAR_FLAG(F_AF);
 6286         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6287         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6288         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6289         return res;
 6290 }
 6291 
 6292 /*
 6293  * REMARKS:
 6294  * Implements the CMP instruction and side effects.
 6295  */
 6296 static uint8_t 
 6297 cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6298 {
 6299         uint32_t res;   /* all operands in native machine order */
 6300         uint32_t bc;
 6301 
 6302         res = d - s;
 6303         CLEAR_FLAG(F_CF);
 6304         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6305         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 6306         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6307 
 6308         /* calculate the borrow chain.  See note at top */
 6309         bc = (res & (~d | s)) | (~d & s);
 6310         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
 6311         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
 6312         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6313         return d;
 6314 }
 6315 
 6316 static void 
 6317 cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
 6318 {
 6319         cmp_byte(emu, d, s);
 6320 }
 6321 
 6322 /*
 6323  * REMARKS:
 6324  * Implements the CMP instruction and side effects.
 6325  */
 6326 static uint16_t 
 6327 cmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
 6328 {
 6329         uint32_t res;   /* all operands in native machine order */
 6330         uint32_t bc;
 6331 
 6332         res = d - s;
 6333         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6334         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 6335         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6336 
 6337         /* calculate the borrow chain.  See note at top */
 6338         bc = (res & (~d | s)) | (~d & s);
 6339         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
 6340         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
 6341         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6342         return d;
 6343 }
 6344 
 6345 static void 
 6346 cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
 6347 {
 6348         cmp_word(emu, d, s);
 6349 }
 6350 
 6351 /*
 6352  * REMARKS:
 6353  * Implements the CMP instruction and side effects.
 6354  */
 6355 static uint32_t 
 6356 cmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
 6357 {
 6358         uint32_t res;   /* all operands in native machine order */
 6359         uint32_t bc;
 6360 
 6361         res = d - s;
 6362         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6363         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 6364         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6365 
 6366         /* calculate the borrow chain.  See note at top */
 6367         bc = (res & (~d | s)) | (~d & s);
 6368         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
 6369         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
 6370         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6371         return d;
 6372 }
 6373 
 6374 static void 
 6375 cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
 6376 {
 6377         cmp_long(emu, d, s);
 6378 }
 6379 
 6380 /*
 6381  * REMARKS:
 6382  * Implements the DAA instruction and side effects.
 6383  */
 6384 static uint8_t 
 6385 daa_byte(struct x86emu *emu, uint8_t d)
 6386 {
 6387         uint32_t res = d;
 6388         if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
 6389                 res += 6;
 6390                 SET_FLAG(F_AF);
 6391         }
 6392         if (res > 0x9F || ACCESS_FLAG(F_CF)) {
 6393                 res += 0x60;
 6394                 SET_FLAG(F_CF);
 6395         }
 6396         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6397         CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
 6398         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6399         return (uint8_t) res;
 6400 }
 6401 
 6402 /*
 6403  * REMARKS:
 6404  * Implements the DAS instruction and side effects.
 6405  */
 6406 static uint8_t 
 6407 das_byte(struct x86emu *emu, uint8_t d)
 6408 {
 6409         if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
 6410                 d -= 6;
 6411                 SET_FLAG(F_AF);
 6412         }
 6413         if (d > 0x9F || ACCESS_FLAG(F_CF)) {
 6414                 d -= 0x60;
 6415                 SET_FLAG(F_CF);
 6416         }
 6417         CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
 6418         CONDITIONAL_SET_FLAG(d == 0, F_ZF);
 6419         CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
 6420         return d;
 6421 }
 6422 
 6423 /*
 6424  * REMARKS:
 6425  * Implements the DEC instruction and side effects.
 6426  */
 6427 static uint8_t 
 6428 dec_byte(struct x86emu *emu, uint8_t d)
 6429 {
 6430         uint32_t res;   /* all operands in native machine order */
 6431         uint32_t bc;
 6432 
 6433         res = d - 1;
 6434         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6435         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 6436         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6437 
 6438         /* calculate the borrow chain.  See note at top */
 6439         /* based on sub_byte, uses s==1.  */
 6440         bc = (res & (~d | 1)) | (~d & 1);
 6441         /* carry flag unchanged */
 6442         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
 6443         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6444         return (uint8_t) res;
 6445 }
 6446 
 6447 /*
 6448  * REMARKS:
 6449  * Implements the DEC instruction and side effects.
 6450  */
 6451 static uint16_t 
 6452 dec_word(struct x86emu *emu, uint16_t d)
 6453 {
 6454         uint32_t res;   /* all operands in native machine order */
 6455         uint32_t bc;
 6456 
 6457         res = d - 1;
 6458         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6459         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 6460         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6461 
 6462         /* calculate the borrow chain.  See note at top */
 6463         /* based on the sub_byte routine, with s==1 */
 6464         bc = (res & (~d | 1)) | (~d & 1);
 6465         /* carry flag unchanged */
 6466         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
 6467         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6468         return (uint16_t) res;
 6469 }
 6470 
 6471 /*
 6472  * REMARKS:
 6473  * Implements the DEC instruction and side effects.
 6474  */
 6475 static uint32_t 
 6476 dec_long(struct x86emu *emu, uint32_t d)
 6477 {
 6478         uint32_t res;   /* all operands in native machine order */
 6479         uint32_t bc;
 6480 
 6481         res = d - 1;
 6482 
 6483         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6484         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 6485         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6486 
 6487         /* calculate the borrow chain.  See note at top */
 6488         bc = (res & (~d | 1)) | (~d & 1);
 6489         /* carry flag unchanged */
 6490         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
 6491         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6492         return res;
 6493 }
 6494 
 6495 /*
 6496  * REMARKS:
 6497  * Implements the INC instruction and side effects.
 6498  */
 6499 static uint8_t 
 6500 inc_byte(struct x86emu *emu, uint8_t d)
 6501 {
 6502         uint32_t res;   /* all operands in native machine order */
 6503         uint32_t cc;
 6504 
 6505         res = d + 1;
 6506         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 6507         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6508         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6509 
 6510         /* calculate the carry chain  SEE NOTE AT TOP. */
 6511         cc = ((1 & d) | (~res)) & (1 | d);
 6512         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
 6513         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6514         return (uint8_t) res;
 6515 }
 6516 
 6517 /*
 6518  * REMARKS:
 6519  * Implements the INC instruction and side effects.
 6520  */
 6521 static uint16_t 
 6522 inc_word(struct x86emu *emu, uint16_t d)
 6523 {
 6524         uint32_t res;   /* all operands in native machine order */
 6525         uint32_t cc;
 6526 
 6527         res = d + 1;
 6528         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 6529         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6530         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6531 
 6532         /* calculate the carry chain  SEE NOTE AT TOP. */
 6533         cc = (1 & d) | ((~res) & (1 | d));
 6534         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
 6535         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6536         return (uint16_t) res;
 6537 }
 6538 
 6539 /*
 6540  * REMARKS:
 6541  * Implements the INC instruction and side effects.
 6542  */
 6543 static uint32_t 
 6544 inc_long(struct x86emu *emu, uint32_t d)
 6545 {
 6546         uint32_t res;   /* all operands in native machine order */
 6547         uint32_t cc;
 6548 
 6549         res = d + 1;
 6550         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 6551         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6552         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6553 
 6554         /* calculate the carry chain  SEE NOTE AT TOP. */
 6555         cc = (1 & d) | ((~res) & (1 | d));
 6556         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
 6557         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 6558         return res;
 6559 }
 6560 
 6561 /*
 6562  * REMARKS:
 6563  * Implements the OR instruction and side effects.
 6564  */
 6565 static uint8_t 
 6566 or_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6567 {
 6568         uint8_t res;    /* all operands in native machine order */
 6569 
 6570         res = d | s;
 6571         CLEAR_FLAG(F_OF);
 6572         CLEAR_FLAG(F_CF);
 6573         CLEAR_FLAG(F_AF);
 6574         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6575         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6576         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
 6577         return res;
 6578 }
 6579 
 6580 /*
 6581  * REMARKS:
 6582  * Implements the OR instruction and side effects.
 6583  */
 6584 static uint16_t 
 6585 or_word(struct x86emu *emu, uint16_t d, uint16_t s)
 6586 {
 6587         uint16_t res;   /* all operands in native machine order */
 6588 
 6589         res = d | s;
 6590         /* set the carry flag to be bit 8 */
 6591         CLEAR_FLAG(F_OF);
 6592         CLEAR_FLAG(F_CF);
 6593         CLEAR_FLAG(F_AF);
 6594         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6595         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6596         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6597         return res;
 6598 }
 6599 
 6600 /*
 6601  * REMARKS:
 6602  * Implements the OR instruction and side effects.
 6603  */
 6604 static uint32_t 
 6605 or_long(struct x86emu *emu, uint32_t d, uint32_t s)
 6606 {
 6607         uint32_t res;   /* all operands in native machine order */
 6608 
 6609         res = d | s;
 6610 
 6611         /* set the carry flag to be bit 8 */
 6612         CLEAR_FLAG(F_OF);
 6613         CLEAR_FLAG(F_CF);
 6614         CLEAR_FLAG(F_AF);
 6615         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6616         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 6617         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6618         return res;
 6619 }
 6620 
 6621 /*
 6622  * REMARKS:
 6623  * Implements the OR instruction and side effects.
 6624  */
 6625 static uint8_t 
 6626 neg_byte(struct x86emu *emu, uint8_t s)
 6627 {
 6628         uint8_t res;
 6629         uint8_t bc;
 6630 
 6631         CONDITIONAL_SET_FLAG(s != 0, F_CF);
 6632         res = (uint8_t) - s;
 6633         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 6634         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 6635         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
 6636         /* calculate the borrow chain --- modified such that d=0.
 6637          * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
 6638          * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
 6639          * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
 6640          * result is: */
 6641         bc = res | s;
 6642         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
 6643         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6644         return res;
 6645 }
 6646 
 6647 /*
 6648  * REMARKS:
 6649  * Implements the OR instruction and side effects.
 6650  */
 6651 static uint16_t 
 6652 neg_word(struct x86emu *emu, uint16_t s)
 6653 {
 6654         uint16_t res;
 6655         uint16_t bc;
 6656 
 6657         CONDITIONAL_SET_FLAG(s != 0, F_CF);
 6658         res = (uint16_t) - s;
 6659         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 6660         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 6661         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6662 
 6663         /* calculate the borrow chain --- modified such that d=0.
 6664          * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
 6665          * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
 6666          * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
 6667          * result is: */
 6668         bc = res | s;
 6669         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
 6670         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6671         return res;
 6672 }
 6673 
 6674 /*
 6675  * REMARKS:
 6676  * Implements the OR instruction and side effects.
 6677  */
 6678 static uint32_t 
 6679 neg_long(struct x86emu *emu, uint32_t s)
 6680 {
 6681         uint32_t res;
 6682         uint32_t bc;
 6683 
 6684         CONDITIONAL_SET_FLAG(s != 0, F_CF);
 6685         res = (uint32_t) - s;
 6686         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 6687         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 6688         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 6689 
 6690         /* calculate the borrow chain --- modified such that d=0.
 6691          * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
 6692          * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
 6693          * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
 6694          * result is: */
 6695         bc = res | s;
 6696         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
 6697         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 6698         return res;
 6699 }
 6700 
 6701 /*
 6702  * REMARKS:
 6703  * Implements the RCL instruction and side effects.
 6704  */
 6705 static uint8_t 
 6706 rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6707 {
 6708         unsigned int res, cnt, mask, cf;
 6709 
 6710         /* s is the rotate distance.  It varies from 0 - 8. */
 6711         /* have
 6712          * 
 6713          * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
 6714          * 
 6715          * want to rotate through the carry by "s" bits.  We could loop, but
 6716          * that's inefficient.  So the width is 9, and we split into three
 6717          * parts:
 6718          * 
 6719          * The new carry flag   (was B_n) the stuff in B_n-1 .. B_0 the stuff
 6720          * in B_7 .. B_n+1
 6721          * 
 6722          * The new rotate is done mod 9, and given this, for a rotation of n
 6723          * bits (mod 9) the new carry flag is then located n bits from the MSB.
 6724          * The low part is then shifted up cnt bits, and the high part is or'd
 6725          * in.  Using CAPS for new values, and lowercase for the original
 6726          * values, this can be expressed as:
 6727          * 
 6728          * IF n > 0 1) CF <-  b_(8-n) 2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
 6729          * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
 6730          */
 6731         res = d;
 6732         if ((cnt = s % 9) != 0) {
 6733                 /* extract the new CARRY FLAG. */
 6734                 /* CF <-  b_(8-n)             */
 6735                 cf = (d >> (8 - cnt)) & 0x1;
 6736 
 6737                 /* 
 6738                  * Get the low stuff which rotated into the range B_7 .. B_cnt
 6739                  * B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
 6740                  * note that the right hand side done by the mask.
 6741                  */
 6742                 res = (d << cnt) & 0xff;
 6743 
 6744                 /* 
 6745                  * now the high stuff which rotated around into the positions
 6746                  * B_cnt-2 .. B_0
 6747                  * B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
 6748                  * shift it downward, 7-(n-2) = 9-n positions. and mask off
 6749                  * the result before or'ing in.
 6750                  */
 6751                 mask = (1 << (cnt - 1)) - 1;
 6752                 res |= (d >> (9 - cnt)) & mask;
 6753 
 6754                 /* if the carry flag was set, or it in.  */
 6755                 if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
 6756                         /* B_(n-1) <- cf */
 6757                         res |= 1 << (cnt - 1);
 6758                 }
 6759                 /* set the new carry flag, based on the variable "cf" */
 6760                 CONDITIONAL_SET_FLAG(cf, F_CF);
 6761                 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
 6762                  * the most significant bit.  Blecck. */
 6763                 /* parenthesized this expression since it appears to be
 6764                  * causing OF to be misset */
 6765                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
 6766                     F_OF);
 6767 
 6768         }
 6769         return (uint8_t) res;
 6770 }
 6771 
 6772 /*
 6773  * REMARKS:
 6774  * Implements the RCL instruction and side effects.
 6775  */
 6776 static uint16_t 
 6777 rcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
 6778 {
 6779         unsigned int res, cnt, mask, cf;
 6780 
 6781         res = d;
 6782         if ((cnt = s % 17) != 0) {
 6783                 cf = (d >> (16 - cnt)) & 0x1;
 6784                 res = (d << cnt) & 0xffff;
 6785                 mask = (1 << (cnt - 1)) - 1;
 6786                 res |= (d >> (17 - cnt)) & mask;
 6787                 if (ACCESS_FLAG(F_CF)) {
 6788                         res |= 1 << (cnt - 1);
 6789                 }
 6790                 CONDITIONAL_SET_FLAG(cf, F_CF);
 6791                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
 6792                     F_OF);
 6793         }
 6794         return (uint16_t) res;
 6795 }
 6796 
 6797 /*
 6798  * REMARKS:
 6799  * Implements the RCL instruction and side effects.
 6800  */
 6801 static uint32_t 
 6802 rcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
 6803 {
 6804         uint32_t res, cnt, mask, cf;
 6805 
 6806         res = d;
 6807         if ((cnt = s % 33) != 0) {
 6808                 cf = (d >> (32 - cnt)) & 0x1;
 6809                 res = (d << cnt) & 0xffffffff;
 6810                 mask = (1 << (cnt - 1)) - 1;
 6811                 res |= (d >> (33 - cnt)) & mask;
 6812                 if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
 6813                         res |= 1 << (cnt - 1);
 6814                 }
 6815                 CONDITIONAL_SET_FLAG(cf, F_CF);
 6816                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
 6817                     F_OF);
 6818         }
 6819         return res;
 6820 }
 6821 
 6822 /*
 6823  * REMARKS:
 6824  * Implements the RCR instruction and side effects.
 6825  */
 6826 static uint8_t 
 6827 rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6828 {
 6829         uint32_t res, cnt;
 6830         uint32_t mask, cf, ocf = 0;
 6831 
 6832         /* rotate right through carry */
 6833         /* s is the rotate distance.  It varies from 0 - 8. d is the byte
 6834          * object rotated.
 6835          * 
 6836          * have
 6837          * 
 6838          * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
 6839          * 
 6840          * The new rotate is done mod 9, and given this, for a rotation of n
 6841          * bits (mod 9) the new carry flag is then located n bits from the LSB.
 6842          * The low part is then shifted up cnt bits, and the high part is or'd
 6843          * in.  Using CAPS for new values, and lowercase for the original
 6844          * values, this can be expressed as:
 6845          * 
 6846          * IF n > 0 
 6847          *      1) CF <-  b_(n-1) 
 6848          *      2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
 6849          *      3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
 6850          */
 6851         res = d;
 6852         if ((cnt = s % 9) != 0) {
 6853                 /* extract the new CARRY FLAG. */
 6854                 /* CF <-  b_(n-1)              */
 6855                 if (cnt == 1) {
 6856                         cf = d & 0x1;
 6857                         /* note hackery here.  Access_flag(..) evaluates to
 6858                          * either 0 if flag not set non-zero if flag is set.
 6859                          * doing access_flag(..) != 0 casts that into either
 6860                          * 0..1 in any representation of the flags register
 6861                          * (i.e. packed bit array or unpacked.) */
 6862                         ocf = ACCESS_FLAG(F_CF) != 0;
 6863                 } else
 6864                         cf = (d >> (cnt - 1)) & 0x1;
 6865 
 6866                 /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
 6867                 /* note that the right hand side done by the mask This is
 6868                  * effectively done by shifting the object to the right.  The
 6869                  * result must be masked, in case the object came in and was
 6870                  * treated as a negative number.  Needed??? */
 6871 
 6872                 mask = (1 << (8 - cnt)) - 1;
 6873                 res = (d >> cnt) & mask;
 6874 
 6875                 /* now the high stuff which rotated around into the positions
 6876                  * B_cnt-2 .. B_0 */
 6877                 /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
 6878                 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
 6879                  * the result before or'ing in. */
 6880                 res |= (d << (9 - cnt));
 6881 
 6882                 /* if the carry flag was set, or it in.  */
 6883                 if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
 6884                         /* B_(8-n) <- cf */
 6885                         res |= 1 << (8 - cnt);
 6886                 }
 6887                 /* set the new carry flag, based on the variable "cf" */
 6888                 CONDITIONAL_SET_FLAG(cf, F_CF);
 6889                 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
 6890                  * the most significant bit.  Blecck. */
 6891                 /* parenthesized... */
 6892                 if (cnt == 1) {
 6893                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
 6894                             F_OF);
 6895                 }
 6896         }
 6897         return (uint8_t) res;
 6898 }
 6899 
 6900 /*
 6901  * REMARKS:
 6902  * Implements the RCR instruction and side effects.
 6903  */
 6904 static uint16_t 
 6905 rcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
 6906 {
 6907         uint32_t res, cnt;
 6908         uint32_t mask, cf, ocf = 0;
 6909 
 6910         /* rotate right through carry */
 6911         res = d;
 6912         if ((cnt = s % 17) != 0) {
 6913                 if (cnt == 1) {
 6914                         cf = d & 0x1;
 6915                         ocf = ACCESS_FLAG(F_CF) != 0;
 6916                 } else
 6917                         cf = (d >> (cnt - 1)) & 0x1;
 6918                 mask = (1 << (16 - cnt)) - 1;
 6919                 res = (d >> cnt) & mask;
 6920                 res |= (d << (17 - cnt));
 6921                 if (ACCESS_FLAG(F_CF)) {
 6922                         res |= 1 << (16 - cnt);
 6923                 }
 6924                 CONDITIONAL_SET_FLAG(cf, F_CF);
 6925                 if (cnt == 1) {
 6926                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
 6927                             F_OF);
 6928                 }
 6929         }
 6930         return (uint16_t) res;
 6931 }
 6932 
 6933 /*
 6934  * REMARKS:
 6935  * Implements the RCR instruction and side effects.
 6936  */
 6937 static uint32_t 
 6938 rcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
 6939 {
 6940         uint32_t res, cnt;
 6941         uint32_t mask, cf, ocf = 0;
 6942 
 6943         /* rotate right through carry */
 6944         res = d;
 6945         if ((cnt = s % 33) != 0) {
 6946                 if (cnt == 1) {
 6947                         cf = d & 0x1;
 6948                         ocf = ACCESS_FLAG(F_CF) != 0;
 6949                 } else
 6950                         cf = (d >> (cnt - 1)) & 0x1;
 6951                 mask = (1 << (32 - cnt)) - 1;
 6952                 res = (d >> cnt) & mask;
 6953                 if (cnt != 1)
 6954                         res |= (d << (33 - cnt));
 6955                 if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
 6956                         res |= 1 << (32 - cnt);
 6957                 }
 6958                 CONDITIONAL_SET_FLAG(cf, F_CF);
 6959                 if (cnt == 1) {
 6960                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
 6961                             F_OF);
 6962                 }
 6963         }
 6964         return res;
 6965 }
 6966 
 6967 /*
 6968  * REMARKS:
 6969  * Implements the ROL instruction and side effects.
 6970  */
 6971 static uint8_t 
 6972 rol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 6973 {
 6974         unsigned int res, cnt, mask;
 6975 
 6976         /* rotate left */
 6977         /* s is the rotate distance.  It varies from 0 - 8. d is the byte
 6978          * object rotated.
 6979          * 
 6980          * have
 6981          * 
 6982          * CF  B_7 ... B_0
 6983          * 
 6984          * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
 6985          * operations.
 6986          * 
 6987          * IF n > 0 1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
 6988          * B_(0) <-  b_(7) .. b_(8-n) */
 6989         res = d;
 6990         if ((cnt = s % 8) != 0) {
 6991                 /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
 6992                 res = (d << cnt);
 6993 
 6994                 /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
 6995                 mask = (1 << cnt) - 1;
 6996                 res |= (d >> (8 - cnt)) & mask;
 6997 
 6998                 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
 6999                  * the most significant bit.  Blecck. */
 7000                 CONDITIONAL_SET_FLAG(s == 1 &&
 7001                     XOR2((res & 0x1) + ((res >> 6) & 0x2)),
 7002                     F_OF);
 7003         }
 7004         if (s != 0) {
 7005                 /* set the new carry flag, Note that it is the low order bit
 7006                  * of the result!!!                               */
 7007                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 7008         }
 7009         return (uint8_t) res;
 7010 }
 7011 
 7012 /*
 7013  * REMARKS:
 7014  * Implements the ROL instruction and side effects.
 7015  */
 7016 static uint16_t 
 7017 rol_word(struct x86emu *emu, uint16_t d, uint8_t s)
 7018 {
 7019         unsigned int res, cnt, mask;
 7020 
 7021         res = d;
 7022         if ((cnt = s % 16) != 0) {
 7023                 res = (d << cnt);
 7024                 mask = (1 << cnt) - 1;
 7025                 res |= (d >> (16 - cnt)) & mask;
 7026                 CONDITIONAL_SET_FLAG(s == 1 &&
 7027                     XOR2((res & 0x1) + ((res >> 14) & 0x2)),
 7028                     F_OF);
 7029         }
 7030         if (s != 0) {
 7031                 /* set the new carry flag, Note that it is the low order bit
 7032                  * of the result!!!                               */
 7033                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 7034         }
 7035         return (uint16_t) res;
 7036 }
 7037 
 7038 /*
 7039  * REMARKS:
 7040  * Implements the ROL instruction and side effects.
 7041  */
 7042 static uint32_t 
 7043 rol_long(struct x86emu *emu, uint32_t d, uint8_t s)
 7044 {
 7045         uint32_t res, cnt, mask;
 7046 
 7047         res = d;
 7048         if ((cnt = s % 32) != 0) {
 7049                 res = (d << cnt);
 7050                 mask = (1 << cnt) - 1;
 7051                 res |= (d >> (32 - cnt)) & mask;
 7052                 CONDITIONAL_SET_FLAG(s == 1 &&
 7053                     XOR2((res & 0x1) + ((res >> 30) & 0x2)),
 7054                     F_OF);
 7055         }
 7056         if (s != 0) {
 7057                 /* set the new carry flag, Note that it is the low order bit
 7058                  * of the result!!!                               */
 7059                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
 7060         }
 7061         return res;
 7062 }
 7063 
 7064 /*
 7065  * REMARKS:
 7066  * Implements the ROR instruction and side effects.
 7067  */
 7068 static uint8_t 
 7069 ror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7070 {
 7071         unsigned int res, cnt, mask;
 7072 
 7073         /* rotate right */
 7074         /* s is the rotate distance.  It varies from 0 - 8. d is the byte
 7075          * object rotated.
 7076          * 
 7077          * have
 7078          * 
 7079          * B_7 ... B_0
 7080          * 
 7081          * The rotate is done mod 8.
 7082          * 
 7083          * IF n > 0 1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) 2) B_(7) ..
 7084          * B_(8-n) <-  b_(n-1) .. b_(0) */
 7085         res = d;
 7086         if ((cnt = s % 8) != 0) {       /* not a typo, do nada if cnt==0 */
 7087                 /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
 7088                 res = (d << (8 - cnt));
 7089 
 7090                 /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
 7091                 mask = (1 << (8 - cnt)) - 1;
 7092                 res |= (d >> (cnt)) & mask;
 7093 
 7094                 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
 7095                  * most significant bits.  Blecck. */
 7096                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
 7097         }
 7098         if (s != 0) {
 7099                 /* set the new carry flag, Note that it is the high order bit
 7100                  * of the result!!!                               */
 7101                 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
 7102         }
 7103         return (uint8_t) res;
 7104 }
 7105 
 7106 /*
 7107  * REMARKS:
 7108  * Implements the ROR instruction and side effects.
 7109  */
 7110 static uint16_t 
 7111 ror_word(struct x86emu *emu, uint16_t d, uint8_t s)
 7112 {
 7113         unsigned int res, cnt, mask;
 7114 
 7115         res = d;
 7116         if ((cnt = s % 16) != 0) {
 7117                 res = (d << (16 - cnt));
 7118                 mask = (1 << (16 - cnt)) - 1;
 7119                 res |= (d >> (cnt)) & mask;
 7120                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
 7121         }
 7122         if (s != 0) {
 7123                 /* set the new carry flag, Note that it is the high order bit
 7124                  * of the result!!!                               */
 7125                 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
 7126         }
 7127         return (uint16_t) res;
 7128 }
 7129 
 7130 /*
 7131  * REMARKS:
 7132  * Implements the ROR instruction and side effects.
 7133  */
 7134 static uint32_t 
 7135 ror_long(struct x86emu *emu, uint32_t d, uint8_t s)
 7136 {
 7137         uint32_t res, cnt, mask;
 7138 
 7139         res = d;
 7140         if ((cnt = s % 32) != 0) {
 7141                 res = (d << (32 - cnt));
 7142                 mask = (1 << (32 - cnt)) - 1;
 7143                 res |= (d >> (cnt)) & mask;
 7144                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
 7145         }
 7146         if (s != 0) {
 7147                 /* set the new carry flag, Note that it is the high order bit
 7148                  * of the result!!!                               */
 7149                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
 7150         }
 7151         return res;
 7152 }
 7153 
 7154 /*
 7155  * REMARKS:
 7156  * Implements the SHL instruction and side effects.
 7157  */
 7158 static uint8_t 
 7159 shl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7160 {
 7161         unsigned int cnt, res, cf;
 7162 
 7163         if (s < 8) {
 7164                 cnt = s % 8;
 7165 
 7166                 /* last bit shifted out goes into carry flag */
 7167                 if (cnt > 0) {
 7168                         res = d << cnt;
 7169                         cf = d & (1 << (8 - cnt));
 7170                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7171                         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 7172                         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7173                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7174                 } else {
 7175                         res = (uint8_t) d;
 7176                 }
 7177 
 7178                 if (cnt == 1) {
 7179                         /* Needs simplification. */
 7180                         CONDITIONAL_SET_FLAG(
 7181                             (((res & 0x80) == 0x80) ^
 7182                                 (ACCESS_FLAG(F_CF) != 0)),
 7183                         /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
 7184                             F_OF);
 7185                 } else {
 7186                         CLEAR_FLAG(F_OF);
 7187                 }
 7188         } else {
 7189                 res = 0;
 7190                 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
 7191                 CLEAR_FLAG(F_OF);
 7192                 CLEAR_FLAG(F_SF);
 7193                 SET_FLAG(F_PF);
 7194                 SET_FLAG(F_ZF);
 7195         }
 7196         return (uint8_t) res;
 7197 }
 7198 
 7199 /*
 7200  * REMARKS:
 7201  * Implements the SHL instruction and side effects.
 7202  */
 7203 static uint16_t 
 7204 shl_word(struct x86emu *emu, uint16_t d, uint8_t s)
 7205 {
 7206         unsigned int cnt, res, cf;
 7207 
 7208         if (s < 16) {
 7209                 cnt = s % 16;
 7210                 if (cnt > 0) {
 7211                         res = d << cnt;
 7212                         cf = d & (1 << (16 - cnt));
 7213                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7214                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7215                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7216                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7217                 } else {
 7218                         res = (uint16_t) d;
 7219                 }
 7220 
 7221                 if (cnt == 1) {
 7222                         CONDITIONAL_SET_FLAG(
 7223                             (((res & 0x8000) == 0x8000) ^
 7224                                 (ACCESS_FLAG(F_CF) != 0)),
 7225                             F_OF);
 7226                 } else {
 7227                         CLEAR_FLAG(F_OF);
 7228                 }
 7229         } else {
 7230                 res = 0;
 7231                 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
 7232                 CLEAR_FLAG(F_OF);
 7233                 CLEAR_FLAG(F_SF);
 7234                 SET_FLAG(F_PF);
 7235                 SET_FLAG(F_ZF);
 7236         }
 7237         return (uint16_t) res;
 7238 }
 7239 
 7240 /*
 7241  * REMARKS:
 7242  * Implements the SHL instruction and side effects.
 7243  */
 7244 static uint32_t 
 7245 shl_long(struct x86emu *emu, uint32_t d, uint8_t s)
 7246 {
 7247         unsigned int cnt, res, cf;
 7248 
 7249         if (s < 32) {
 7250                 cnt = s % 32;
 7251                 if (cnt > 0) {
 7252                         res = d << cnt;
 7253                         cf = d & (1 << (32 - cnt));
 7254                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7255                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7256                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7257                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7258                 } else {
 7259                         res = d;
 7260                 }
 7261                 if (cnt == 1) {
 7262                         CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
 7263                             ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
 7264                 } else {
 7265                         CLEAR_FLAG(F_OF);
 7266                 }
 7267         } else {
 7268                 res = 0;
 7269                 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
 7270                 CLEAR_FLAG(F_OF);
 7271                 CLEAR_FLAG(F_SF);
 7272                 SET_FLAG(F_PF);
 7273                 SET_FLAG(F_ZF);
 7274         }
 7275         return res;
 7276 }
 7277 
 7278 /*
 7279  * REMARKS:
 7280  * Implements the SHR instruction and side effects.
 7281  */
 7282 static uint8_t 
 7283 shr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7284 {
 7285         unsigned int cnt, res, cf;
 7286 
 7287         if (s < 8) {
 7288                 cnt = s % 8;
 7289                 if (cnt > 0) {
 7290                         cf = d & (1 << (cnt - 1));
 7291                         res = d >> cnt;
 7292                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7293                         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 7294                         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7295                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7296                 } else {
 7297                         res = (uint8_t) d;
 7298                 }
 7299 
 7300                 if (cnt == 1) {
 7301                         CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
 7302                 } else {
 7303                         CLEAR_FLAG(F_OF);
 7304                 }
 7305         } else {
 7306                 res = 0;
 7307                 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
 7308                 CLEAR_FLAG(F_OF);
 7309                 CLEAR_FLAG(F_SF);
 7310                 SET_FLAG(F_PF);
 7311                 SET_FLAG(F_ZF);
 7312         }
 7313         return (uint8_t) res;
 7314 }
 7315 
 7316 /*
 7317  * REMARKS:
 7318  * Implements the SHR instruction and side effects.
 7319  */
 7320 static uint16_t 
 7321 shr_word(struct x86emu *emu, uint16_t d, uint8_t s)
 7322 {
 7323         unsigned int cnt, res, cf;
 7324 
 7325         if (s < 16) {
 7326                 cnt = s % 16;
 7327                 if (cnt > 0) {
 7328                         cf = d & (1 << (cnt - 1));
 7329                         res = d >> cnt;
 7330                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7331                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7332                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7333                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7334                 } else {
 7335                         res = d;
 7336                 }
 7337 
 7338                 if (cnt == 1) {
 7339                         CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
 7340                 } else {
 7341                         CLEAR_FLAG(F_OF);
 7342                 }
 7343         } else {
 7344                 res = 0;
 7345                 CLEAR_FLAG(F_CF);
 7346                 CLEAR_FLAG(F_OF);
 7347                 SET_FLAG(F_ZF);
 7348                 CLEAR_FLAG(F_SF);
 7349                 CLEAR_FLAG(F_PF);
 7350         }
 7351         return (uint16_t) res;
 7352 }
 7353 
 7354 /*
 7355  * REMARKS:
 7356  * Implements the SHR instruction and side effects.
 7357  */
 7358 static uint32_t 
 7359 shr_long(struct x86emu *emu, uint32_t d, uint8_t s)
 7360 {
 7361         unsigned int cnt, res, cf;
 7362 
 7363         if (s < 32) {
 7364                 cnt = s % 32;
 7365                 if (cnt > 0) {
 7366                         cf = d & (1 << (cnt - 1));
 7367                         res = d >> cnt;
 7368                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7369                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7370                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7371                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7372                 } else {
 7373                         res = d;
 7374                 }
 7375                 if (cnt == 1) {
 7376                         CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
 7377                 } else {
 7378                         CLEAR_FLAG(F_OF);
 7379                 }
 7380         } else {
 7381                 res = 0;
 7382                 CLEAR_FLAG(F_CF);
 7383                 CLEAR_FLAG(F_OF);
 7384                 SET_FLAG(F_ZF);
 7385                 CLEAR_FLAG(F_SF);
 7386                 CLEAR_FLAG(F_PF);
 7387         }
 7388         return res;
 7389 }
 7390 
 7391 /*
 7392  * REMARKS:
 7393  * Implements the SAR instruction and side effects.
 7394  */
 7395 static uint8_t 
 7396 sar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7397 {
 7398         unsigned int cnt, res, cf, mask, sf;
 7399 
 7400         res = d;
 7401         sf = d & 0x80;
 7402         cnt = s % 8;
 7403         if (cnt > 0 && cnt < 8) {
 7404                 mask = (1 << (8 - cnt)) - 1;
 7405                 cf = d & (1 << (cnt - 1));
 7406                 res = (d >> cnt) & mask;
 7407                 CONDITIONAL_SET_FLAG(cf, F_CF);
 7408                 if (sf) {
 7409                         res |= ~mask;
 7410                 }
 7411                 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 7412                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7413                 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7414         } else if (cnt >= 8) {
 7415                 if (sf) {
 7416                         res = 0xff;
 7417                         SET_FLAG(F_CF);
 7418                         CLEAR_FLAG(F_ZF);
 7419                         SET_FLAG(F_SF);
 7420                         SET_FLAG(F_PF);
 7421                 } else {
 7422                         res = 0;
 7423                         CLEAR_FLAG(F_CF);
 7424                         SET_FLAG(F_ZF);
 7425                         CLEAR_FLAG(F_SF);
 7426                         CLEAR_FLAG(F_PF);
 7427                 }
 7428         }
 7429         return (uint8_t) res;
 7430 }
 7431 
 7432 /*
 7433  * REMARKS:
 7434  * Implements the SAR instruction and side effects.
 7435  */
 7436 static uint16_t 
 7437 sar_word(struct x86emu *emu, uint16_t d, uint8_t s)
 7438 {
 7439         unsigned int cnt, res, cf, mask, sf;
 7440 
 7441         sf = d & 0x8000;
 7442         cnt = s % 16;
 7443         res = d;
 7444         if (cnt > 0 && cnt < 16) {
 7445                 mask = (1 << (16 - cnt)) - 1;
 7446                 cf = d & (1 << (cnt - 1));
 7447                 res = (d >> cnt) & mask;
 7448                 CONDITIONAL_SET_FLAG(cf, F_CF);
 7449                 if (sf) {
 7450                         res |= ~mask;
 7451                 }
 7452                 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7453                 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7454                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7455         } else if (cnt >= 16) {
 7456                 if (sf) {
 7457                         res = 0xffff;
 7458                         SET_FLAG(F_CF);
 7459                         CLEAR_FLAG(F_ZF);
 7460                         SET_FLAG(F_SF);
 7461                         SET_FLAG(F_PF);
 7462                 } else {
 7463                         res = 0;
 7464                         CLEAR_FLAG(F_CF);
 7465                         SET_FLAG(F_ZF);
 7466                         CLEAR_FLAG(F_SF);
 7467                         CLEAR_FLAG(F_PF);
 7468                 }
 7469         }
 7470         return (uint16_t) res;
 7471 }
 7472 
 7473 /*
 7474  * REMARKS:
 7475  * Implements the SAR instruction and side effects.
 7476  */
 7477 static uint32_t 
 7478 sar_long(struct x86emu *emu, uint32_t d, uint8_t s)
 7479 {
 7480         uint32_t cnt, res, cf, mask, sf;
 7481 
 7482         sf = d & 0x80000000;
 7483         cnt = s % 32;
 7484         res = d;
 7485         if (cnt > 0 && cnt < 32) {
 7486                 mask = (1 << (32 - cnt)) - 1;
 7487                 cf = d & (1 << (cnt - 1));
 7488                 res = (d >> cnt) & mask;
 7489                 CONDITIONAL_SET_FLAG(cf, F_CF);
 7490                 if (sf) {
 7491                         res |= ~mask;
 7492                 }
 7493                 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7494                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7495                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7496         } else if (cnt >= 32) {
 7497                 if (sf) {
 7498                         res = 0xffffffff;
 7499                         SET_FLAG(F_CF);
 7500                         CLEAR_FLAG(F_ZF);
 7501                         SET_FLAG(F_SF);
 7502                         SET_FLAG(F_PF);
 7503                 } else {
 7504                         res = 0;
 7505                         CLEAR_FLAG(F_CF);
 7506                         SET_FLAG(F_ZF);
 7507                         CLEAR_FLAG(F_SF);
 7508                         CLEAR_FLAG(F_PF);
 7509                 }
 7510         }
 7511         return res;
 7512 }
 7513 
 7514 /*
 7515  * REMARKS:
 7516  * Implements the SHLD instruction and side effects.
 7517  */
 7518 static uint16_t 
 7519 shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
 7520 {
 7521         unsigned int cnt, res, cf;
 7522 
 7523         if (s < 16) {
 7524                 cnt = s % 16;
 7525                 if (cnt > 0) {
 7526                         res = (d << cnt) | (fill >> (16 - cnt));
 7527                         cf = d & (1 << (16 - cnt));
 7528                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7529                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7530                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7531                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7532                 } else {
 7533                         res = d;
 7534                 }
 7535                 if (cnt == 1) {
 7536                         CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
 7537                                 (ACCESS_FLAG(F_CF) != 0)), F_OF);
 7538                 } else {
 7539                         CLEAR_FLAG(F_OF);
 7540                 }
 7541         } else {
 7542                 res = 0;
 7543                 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
 7544                 CLEAR_FLAG(F_OF);
 7545                 CLEAR_FLAG(F_SF);
 7546                 SET_FLAG(F_PF);
 7547                 SET_FLAG(F_ZF);
 7548         }
 7549         return (uint16_t) res;
 7550 }
 7551 
 7552 /*
 7553  * REMARKS:
 7554  * Implements the SHLD instruction and side effects.
 7555  */
 7556 static uint32_t 
 7557 shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
 7558 {
 7559         unsigned int cnt, res, cf;
 7560 
 7561         if (s < 32) {
 7562                 cnt = s % 32;
 7563                 if (cnt > 0) {
 7564                         res = (d << cnt) | (fill >> (32 - cnt));
 7565                         cf = d & (1 << (32 - cnt));
 7566                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7567                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7568                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7569                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7570                 } else {
 7571                         res = d;
 7572                 }
 7573                 if (cnt == 1) {
 7574                         CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
 7575                             ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
 7576                 } else {
 7577                         CLEAR_FLAG(F_OF);
 7578                 }
 7579         } else {
 7580                 res = 0;
 7581                 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
 7582                 CLEAR_FLAG(F_OF);
 7583                 CLEAR_FLAG(F_SF);
 7584                 SET_FLAG(F_PF);
 7585                 SET_FLAG(F_ZF);
 7586         }
 7587         return res;
 7588 }
 7589 
 7590 /*
 7591  * REMARKS:
 7592  * Implements the SHRD instruction and side effects.
 7593  */
 7594 static uint16_t 
 7595 shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
 7596 {
 7597         unsigned int cnt, res, cf;
 7598 
 7599         if (s < 16) {
 7600                 cnt = s % 16;
 7601                 if (cnt > 0) {
 7602                         cf = d & (1 << (cnt - 1));
 7603                         res = (d >> cnt) | (fill << (16 - cnt));
 7604                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7605                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7606                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7607                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7608                 } else {
 7609                         res = d;
 7610                 }
 7611 
 7612                 if (cnt == 1) {
 7613                         CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
 7614                 } else {
 7615                         CLEAR_FLAG(F_OF);
 7616                 }
 7617         } else {
 7618                 res = 0;
 7619                 CLEAR_FLAG(F_CF);
 7620                 CLEAR_FLAG(F_OF);
 7621                 SET_FLAG(F_ZF);
 7622                 CLEAR_FLAG(F_SF);
 7623                 CLEAR_FLAG(F_PF);
 7624         }
 7625         return (uint16_t) res;
 7626 }
 7627 
 7628 /*
 7629  * REMARKS:
 7630  * Implements the SHRD instruction and side effects.
 7631  */
 7632 static uint32_t 
 7633 shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
 7634 {
 7635         unsigned int cnt, res, cf;
 7636 
 7637         if (s < 32) {
 7638                 cnt = s % 32;
 7639                 if (cnt > 0) {
 7640                         cf = d & (1 << (cnt - 1));
 7641                         res = (d >> cnt) | (fill << (32 - cnt));
 7642                         CONDITIONAL_SET_FLAG(cf, F_CF);
 7643                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7644                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7645                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7646                 } else {
 7647                         res = d;
 7648                 }
 7649                 if (cnt == 1) {
 7650                         CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
 7651                 } else {
 7652                         CLEAR_FLAG(F_OF);
 7653                 }
 7654         } else {
 7655                 res = 0;
 7656                 CLEAR_FLAG(F_CF);
 7657                 CLEAR_FLAG(F_OF);
 7658                 SET_FLAG(F_ZF);
 7659                 CLEAR_FLAG(F_SF);
 7660                 CLEAR_FLAG(F_PF);
 7661         }
 7662         return res;
 7663 }
 7664 
 7665 /*
 7666  * REMARKS:
 7667  * Implements the SBB instruction and side effects.
 7668  */
 7669 static uint8_t 
 7670 sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7671 {
 7672         uint32_t res;   /* all operands in native machine order */
 7673         uint32_t bc;
 7674 
 7675         if (ACCESS_FLAG(F_CF))
 7676                 res = d - s - 1;
 7677         else
 7678                 res = d - s;
 7679         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7680         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 7681         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7682 
 7683         /* calculate the borrow chain.  See note at top */
 7684         bc = (res & (~d | s)) | (~d & s);
 7685         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
 7686         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
 7687         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 7688         return (uint8_t) res;
 7689 }
 7690 
 7691 /*
 7692  * REMARKS:
 7693  * Implements the SBB instruction and side effects.
 7694  */
 7695 static uint16_t 
 7696 sbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
 7697 {
 7698         uint32_t res;   /* all operands in native machine order */
 7699         uint32_t bc;
 7700 
 7701         if (ACCESS_FLAG(F_CF))
 7702                 res = d - s - 1;
 7703         else
 7704                 res = d - s;
 7705         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7706         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7707         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7708 
 7709         /* calculate the borrow chain.  See note at top */
 7710         bc = (res & (~d | s)) | (~d & s);
 7711         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
 7712         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
 7713         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 7714         return (uint16_t) res;
 7715 }
 7716 
 7717 /*
 7718  * REMARKS:
 7719  * Implements the SBB instruction and side effects.
 7720  */
 7721 static uint32_t 
 7722 sbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
 7723 {
 7724         uint32_t res;   /* all operands in native machine order */
 7725         uint32_t bc;
 7726 
 7727         if (ACCESS_FLAG(F_CF))
 7728                 res = d - s - 1;
 7729         else
 7730                 res = d - s;
 7731         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7732         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7733         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7734 
 7735         /* calculate the borrow chain.  See note at top */
 7736         bc = (res & (~d | s)) | (~d & s);
 7737         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
 7738         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
 7739         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 7740         return res;
 7741 }
 7742 
 7743 /*
 7744  * REMARKS:
 7745  * Implements the SUB instruction and side effects.
 7746  */
 7747 static uint8_t 
 7748 sub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7749 {
 7750         uint32_t res;   /* all operands in native machine order */
 7751         uint32_t bc;
 7752 
 7753         res = d - s;
 7754         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7755         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
 7756         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7757 
 7758         /* calculate the borrow chain.  See note at top */
 7759         bc = (res & (~d | s)) | (~d & s);
 7760         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
 7761         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
 7762         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 7763         return (uint8_t) res;
 7764 }
 7765 
 7766 /*
 7767  * REMARKS:
 7768  * Implements the SUB instruction and side effects.
 7769  */
 7770 static uint16_t 
 7771 sub_word(struct x86emu *emu, uint16_t d, uint16_t s)
 7772 {
 7773         uint32_t res;   /* all operands in native machine order */
 7774         uint32_t bc;
 7775 
 7776         res = d - s;
 7777         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7778         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
 7779         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7780 
 7781         /* calculate the borrow chain.  See note at top */
 7782         bc = (res & (~d | s)) | (~d & s);
 7783         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
 7784         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
 7785         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 7786         return (uint16_t) res;
 7787 }
 7788 
 7789 /*
 7790  * REMARKS:
 7791  * Implements the SUB instruction and side effects.
 7792  */
 7793 static uint32_t 
 7794 sub_long(struct x86emu *emu, uint32_t d, uint32_t s)
 7795 {
 7796         uint32_t res;   /* all operands in native machine order */
 7797         uint32_t bc;
 7798 
 7799         res = d - s;
 7800         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7801         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
 7802         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7803 
 7804         /* calculate the borrow chain.  See note at top */
 7805         bc = (res & (~d | s)) | (~d & s);
 7806         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
 7807         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
 7808         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 7809         return res;
 7810 }
 7811 
 7812 /*
 7813  * REMARKS:
 7814  * Implements the TEST instruction and side effects.
 7815  */
 7816 static void 
 7817 test_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7818 {
 7819         uint32_t res;   /* all operands in native machine order */
 7820 
 7821         res = d & s;
 7822 
 7823         CLEAR_FLAG(F_OF);
 7824         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7825         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 7826         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7827         /* AF == dont care */
 7828         CLEAR_FLAG(F_CF);
 7829 }
 7830 
 7831 /*
 7832  * REMARKS:
 7833  * Implements the TEST instruction and side effects.
 7834  */
 7835 static void 
 7836 test_word(struct x86emu *emu, uint16_t d, uint16_t s)
 7837 {
 7838         uint32_t res;   /* all operands in native machine order */
 7839 
 7840         res = d & s;
 7841 
 7842         CLEAR_FLAG(F_OF);
 7843         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7844         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 7845         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7846         /* AF == dont care */
 7847         CLEAR_FLAG(F_CF);
 7848 }
 7849 
 7850 /*
 7851  * REMARKS:
 7852  * Implements the TEST instruction and side effects.
 7853  */
 7854 static void 
 7855 test_long(struct x86emu *emu, uint32_t d, uint32_t s)
 7856 {
 7857         uint32_t res;   /* all operands in native machine order */
 7858 
 7859         res = d & s;
 7860 
 7861         CLEAR_FLAG(F_OF);
 7862         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7863         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 7864         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7865         /* AF == dont care */
 7866         CLEAR_FLAG(F_CF);
 7867 }
 7868 
 7869 /*
 7870  * REMARKS:
 7871  * Implements the XOR instruction and side effects.
 7872  */
 7873 static uint8_t 
 7874 xor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
 7875 {
 7876         uint8_t res;    /* all operands in native machine order */
 7877 
 7878         res = d ^ s;
 7879         CLEAR_FLAG(F_OF);
 7880         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 7881         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 7882         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
 7883         CLEAR_FLAG(F_CF);
 7884         CLEAR_FLAG(F_AF);
 7885         return res;
 7886 }
 7887 
 7888 /*
 7889  * REMARKS:
 7890  * Implements the XOR instruction and side effects.
 7891  */
 7892 static uint16_t 
 7893 xor_word(struct x86emu *emu, uint16_t d, uint16_t s)
 7894 {
 7895         uint16_t res;   /* all operands in native machine order */
 7896 
 7897         res = d ^ s;
 7898         CLEAR_FLAG(F_OF);
 7899         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 7900         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 7901         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7902         CLEAR_FLAG(F_CF);
 7903         CLEAR_FLAG(F_AF);
 7904         return res;
 7905 }
 7906 
 7907 /*
 7908  * REMARKS:
 7909  * Implements the XOR instruction and side effects.
 7910  */
 7911 static uint32_t 
 7912 xor_long(struct x86emu *emu, uint32_t d, uint32_t s)
 7913 {
 7914         uint32_t res;   /* all operands in native machine order */
 7915 
 7916         res = d ^ s;
 7917         CLEAR_FLAG(F_OF);
 7918         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 7919         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 7920         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 7921         CLEAR_FLAG(F_CF);
 7922         CLEAR_FLAG(F_AF);
 7923         return res;
 7924 }
 7925 
 7926 /*
 7927  * REMARKS:
 7928  * Implements the IMUL instruction and side effects.
 7929  */
 7930 static void 
 7931 imul_byte(struct x86emu *emu, uint8_t s)
 7932 {
 7933         int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
 7934 
 7935         emu->x86.R_AX = res;
 7936         if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
 7937             ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
 7938                 CLEAR_FLAG(F_CF);
 7939                 CLEAR_FLAG(F_OF);
 7940         } else {
 7941                 SET_FLAG(F_CF);
 7942                 SET_FLAG(F_OF);
 7943         }
 7944 }
 7945 
 7946 /*
 7947  * REMARKS:
 7948  * Implements the IMUL instruction and side effects.
 7949  */
 7950 static void 
 7951 imul_word(struct x86emu *emu, uint16_t s)
 7952 {
 7953         int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
 7954 
 7955         emu->x86.R_AX = (uint16_t) res;
 7956         emu->x86.R_DX = (uint16_t) (res >> 16);
 7957         if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
 7958             ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
 7959                 CLEAR_FLAG(F_CF);
 7960                 CLEAR_FLAG(F_OF);
 7961         } else {
 7962                 SET_FLAG(F_CF);
 7963                 SET_FLAG(F_OF);
 7964         }
 7965 }
 7966 
 7967 /*
 7968  * REMARKS:
 7969  * Implements the IMUL instruction and side effects.
 7970  */
 7971 static void 
 7972 imul_long(struct x86emu *emu, uint32_t s)
 7973 {
 7974         int64_t res;
 7975         
 7976         res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
 7977         emu->x86.R_EAX = (uint32_t)res;
 7978         emu->x86.R_EDX = ((uint64_t)res) >> 32;
 7979         if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
 7980             ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
 7981                 CLEAR_FLAG(F_CF);
 7982                 CLEAR_FLAG(F_OF);
 7983         } else {
 7984                 SET_FLAG(F_CF);
 7985                 SET_FLAG(F_OF);
 7986         }
 7987 }
 7988 
 7989 /*
 7990  * REMARKS:
 7991  * Implements the MUL instruction and side effects.
 7992  */
 7993 static void 
 7994 mul_byte(struct x86emu *emu, uint8_t s)
 7995 {
 7996         uint16_t res = (uint16_t) (emu->x86.R_AL * s);
 7997 
 7998         emu->x86.R_AX = res;
 7999         if (emu->x86.R_AH == 0) {
 8000                 CLEAR_FLAG(F_CF);
 8001                 CLEAR_FLAG(F_OF);
 8002         } else {
 8003                 SET_FLAG(F_CF);
 8004                 SET_FLAG(F_OF);
 8005         }
 8006 }
 8007 
 8008 /*
 8009  * REMARKS:
 8010  * Implements the MUL instruction and side effects.
 8011  */
 8012 static void 
 8013 mul_word(struct x86emu *emu, uint16_t s)
 8014 {
 8015         uint32_t res = emu->x86.R_AX * s;
 8016 
 8017         emu->x86.R_AX = (uint16_t) res;
 8018         emu->x86.R_DX = (uint16_t) (res >> 16);
 8019         if (emu->x86.R_DX == 0) {
 8020                 CLEAR_FLAG(F_CF);
 8021                 CLEAR_FLAG(F_OF);
 8022         } else {
 8023                 SET_FLAG(F_CF);
 8024                 SET_FLAG(F_OF);
 8025         }
 8026 }
 8027 
 8028 /*
 8029  * REMARKS:
 8030  * Implements the MUL instruction and side effects.
 8031  */
 8032 static void 
 8033 mul_long(struct x86emu *emu, uint32_t s)
 8034 {
 8035         uint64_t res = (uint64_t) emu->x86.R_EAX * s;
 8036 
 8037         emu->x86.R_EAX = (uint32_t) res;
 8038         emu->x86.R_EDX = (uint32_t) (res >> 32);
 8039 
 8040         if (emu->x86.R_EDX == 0) {
 8041                 CLEAR_FLAG(F_CF);
 8042                 CLEAR_FLAG(F_OF);
 8043         } else {
 8044                 SET_FLAG(F_CF);
 8045                 SET_FLAG(F_OF);
 8046         }
 8047 }
 8048 
 8049 /*
 8050  * REMARKS:
 8051  * Implements the IDIV instruction and side effects.
 8052  */
 8053 static void 
 8054 idiv_byte(struct x86emu *emu, uint8_t s)
 8055 {
 8056         int32_t dvd, div, mod;
 8057 
 8058         dvd = (int16_t) emu->x86.R_AX;
 8059         if (s == 0) {
 8060                 x86emu_intr_raise(emu, 8);
 8061                 return;
 8062         }
 8063         div = dvd / (int8_t) s;
 8064         mod = dvd % (int8_t) s;
 8065         if (div > 0x7f || div < -0x7f) {
 8066                 x86emu_intr_raise(emu, 8);
 8067                 return;
 8068         }
 8069         emu->x86.R_AL = (int8_t) div;
 8070         emu->x86.R_AH = (int8_t) mod;
 8071 }
 8072 
 8073 /*
 8074  * REMARKS:
 8075  * Implements the IDIV instruction and side effects.
 8076  */
 8077 static void 
 8078 idiv_word(struct x86emu *emu, uint16_t s)
 8079 {
 8080         int32_t dvd, div, mod;
 8081 
 8082         dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
 8083         if (s == 0) {
 8084                 x86emu_intr_raise(emu, 8);
 8085                 return;
 8086         }
 8087         div = dvd / (int16_t) s;
 8088         mod = dvd % (int16_t) s;
 8089         if (div > 0x7fff || div < -0x7fff) {
 8090                 x86emu_intr_raise(emu, 8);
 8091                 return;
 8092         }
 8093         CLEAR_FLAG(F_CF);
 8094         CLEAR_FLAG(F_SF);
 8095         CONDITIONAL_SET_FLAG(div == 0, F_ZF);
 8096         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
 8097 
 8098         emu->x86.R_AX = (uint16_t) div;
 8099         emu->x86.R_DX = (uint16_t) mod;
 8100 }
 8101 
 8102 /*
 8103  * REMARKS:
 8104  * Implements the IDIV instruction and side effects.
 8105  */
 8106 static void 
 8107 idiv_long(struct x86emu *emu, uint32_t s)
 8108 {
 8109         int64_t dvd, div, mod;
 8110 
 8111         dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
 8112         if (s == 0) {
 8113                 x86emu_intr_raise(emu, 8);
 8114                 return;
 8115         }
 8116         div = dvd / (int32_t) s;
 8117         mod = dvd % (int32_t) s;
 8118         if (div > 0x7fffffff || div < -0x7fffffff) {
 8119                 x86emu_intr_raise(emu, 8);
 8120                 return;
 8121         }
 8122         CLEAR_FLAG(F_CF);
 8123         CLEAR_FLAG(F_AF);
 8124         CLEAR_FLAG(F_SF);
 8125         SET_FLAG(F_ZF);
 8126         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
 8127 
 8128         emu->x86.R_EAX = (uint32_t) div;
 8129         emu->x86.R_EDX = (uint32_t) mod;
 8130 }
 8131 
 8132 /*
 8133  * REMARKS:
 8134  * Implements the DIV instruction and side effects.
 8135  */
 8136 static void 
 8137 div_byte(struct x86emu *emu, uint8_t s)
 8138 {
 8139         uint32_t dvd, div, mod;
 8140 
 8141         dvd = emu->x86.R_AX;
 8142         if (s == 0) {
 8143                 x86emu_intr_raise(emu, 8);
 8144                 return;
 8145         }
 8146         div = dvd / (uint8_t) s;
 8147         mod = dvd % (uint8_t) s;
 8148         if (div > 0xff) {
 8149                 x86emu_intr_raise(emu, 8);
 8150                 return;
 8151         }
 8152         emu->x86.R_AL = (uint8_t) div;
 8153         emu->x86.R_AH = (uint8_t) mod;
 8154 }
 8155 
 8156 /*
 8157  * REMARKS:
 8158  * Implements the DIV instruction and side effects.
 8159  */
 8160 static void 
 8161 div_word(struct x86emu *emu, uint16_t s)
 8162 {
 8163         uint32_t dvd, div, mod;
 8164 
 8165         dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
 8166         if (s == 0) {
 8167                 x86emu_intr_raise(emu, 8);
 8168                 return;
 8169         }
 8170         div = dvd / (uint16_t) s;
 8171         mod = dvd % (uint16_t) s;
 8172         if (div > 0xffff) {
 8173                 x86emu_intr_raise(emu, 8);
 8174                 return;
 8175         }
 8176         CLEAR_FLAG(F_CF);
 8177         CLEAR_FLAG(F_SF);
 8178         CONDITIONAL_SET_FLAG(div == 0, F_ZF);
 8179         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
 8180 
 8181         emu->x86.R_AX = (uint16_t) div;
 8182         emu->x86.R_DX = (uint16_t) mod;
 8183 }
 8184 
 8185 /*
 8186  * REMARKS:
 8187  * Implements the DIV instruction and side effects.
 8188  */
 8189 static void 
 8190 div_long(struct x86emu *emu, uint32_t s)
 8191 {
 8192         uint64_t dvd, div, mod;
 8193 
 8194         dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
 8195         if (s == 0) {
 8196                 x86emu_intr_raise(emu, 8);
 8197                 return;
 8198         }
 8199         div = dvd / (uint32_t) s;
 8200         mod = dvd % (uint32_t) s;
 8201         if (div > 0xffffffff) {
 8202                 x86emu_intr_raise(emu, 8);
 8203                 return;
 8204         }
 8205         CLEAR_FLAG(F_CF);
 8206         CLEAR_FLAG(F_AF);
 8207         CLEAR_FLAG(F_SF);
 8208         SET_FLAG(F_ZF);
 8209         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
 8210 
 8211         emu->x86.R_EAX = (uint32_t) div;
 8212         emu->x86.R_EDX = (uint32_t) mod;
 8213 }
 8214 
 8215 /*
 8216  * REMARKS:
 8217  * Implements the IN string instruction and side effects.
 8218  */
 8219 static void 
 8220 ins(struct x86emu *emu, int size)
 8221 {
 8222         int inc = size;
 8223 
 8224         if (ACCESS_FLAG(F_DF)) {
 8225                 inc = -size;
 8226         }
 8227         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 8228                 /* dont care whether REPE or REPNE */
 8229                 /* in until CX is ZERO. */
 8230                 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
 8231                     emu->x86.R_ECX : emu->x86.R_CX);
 8232                 switch (size) {
 8233                 case 1:
 8234                         while (count--) {
 8235                                 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
 8236                                     (*emu->emu_inb) (emu, emu->x86.R_DX));
 8237                                 emu->x86.R_DI += inc;
 8238                         }
 8239                         break;
 8240 
 8241                 case 2:
 8242                         while (count--) {
 8243                                 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
 8244                                     (*emu->emu_inw) (emu, emu->x86.R_DX));
 8245                                 emu->x86.R_DI += inc;
 8246                         }
 8247                         break;
 8248                 case 4:
 8249                         while (count--) {
 8250                                 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
 8251                                     (*emu->emu_inl) (emu, emu->x86.R_DX));
 8252                                 emu->x86.R_DI += inc;
 8253                                 break;
 8254                         }
 8255                 }
 8256                 emu->x86.R_CX = 0;
 8257                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 8258                         emu->x86.R_ECX = 0;
 8259                 }
 8260                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 8261         } else {
 8262                 switch (size) {
 8263                 case 1:
 8264                         store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
 8265                             (*emu->emu_inb) (emu, emu->x86.R_DX));
 8266                         break;
 8267                 case 2:
 8268                         store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
 8269                             (*emu->emu_inw) (emu, emu->x86.R_DX));
 8270                         break;
 8271                 case 4:
 8272                         store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
 8273                             (*emu->emu_inl) (emu, emu->x86.R_DX));
 8274                         break;
 8275                 }
 8276                 emu->x86.R_DI += inc;
 8277         }
 8278 }
 8279 
 8280 /*
 8281  * REMARKS:
 8282  * Implements the OUT string instruction and side effects.
 8283  */
 8284 static void 
 8285 outs(struct x86emu *emu, int size)
 8286 {
 8287         int inc = size;
 8288 
 8289         if (ACCESS_FLAG(F_DF)) {
 8290                 inc = -size;
 8291         }
 8292         if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
 8293                 /* dont care whether REPE or REPNE */
 8294                 /* out until CX is ZERO. */
 8295                 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
 8296                     emu->x86.R_ECX : emu->x86.R_CX);
 8297                 switch (size) {
 8298                 case 1:
 8299                         while (count--) {
 8300                                 (*emu->emu_outb) (emu, emu->x86.R_DX,
 8301                                     fetch_byte(emu, emu->x86.R_ES,
 8302                                     emu->x86.R_SI));
 8303                                 emu->x86.R_SI += inc;
 8304                         }
 8305                         break;
 8306 
 8307                 case 2:
 8308                         while (count--) {
 8309                                 (*emu->emu_outw) (emu, emu->x86.R_DX,
 8310                                     fetch_word(emu, emu->x86.R_ES,
 8311                                     emu->x86.R_SI));
 8312                                 emu->x86.R_SI += inc;
 8313                         }
 8314                         break;
 8315                 case 4:
 8316                         while (count--) {
 8317                                 (*emu->emu_outl) (emu, emu->x86.R_DX,
 8318                                     fetch_long(emu, emu->x86.R_ES,
 8319                                     emu->x86.R_SI));
 8320                                 emu->x86.R_SI += inc;
 8321                                 break;
 8322                         }
 8323                 }
 8324                 emu->x86.R_CX = 0;
 8325                 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
 8326                         emu->x86.R_ECX = 0;
 8327                 }
 8328                 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
 8329         } else {
 8330                 switch (size) {
 8331                 case 1:
 8332                         (*emu->emu_outb) (emu, emu->x86.R_DX,
 8333                             fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
 8334                         break;
 8335                 case 2:
 8336                         (*emu->emu_outw) (emu, emu->x86.R_DX,
 8337                             fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
 8338                         break;
 8339                 case 4:
 8340                         (*emu->emu_outl) (emu, emu->x86.R_DX,
 8341                             fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
 8342                         break;
 8343                 }
 8344                 emu->x86.R_SI += inc;
 8345         }
 8346 }
 8347 
 8348 /*
 8349  * REMARKS:
 8350  * Pushes a word onto the stack.
 8351  * 
 8352  * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
 8353  */
 8354 static void 
 8355 push_word(struct x86emu *emu, uint16_t w)
 8356 {
 8357         emu->x86.R_SP -= 2;
 8358         store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
 8359 }
 8360 
 8361 /*
 8362  * REMARKS:
 8363  * Pushes a long onto the stack.
 8364  * 
 8365  * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
 8366  */
 8367 static void 
 8368 push_long(struct x86emu *emu, uint32_t w)
 8369 {
 8370         emu->x86.R_SP -= 4;
 8371         store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
 8372 }
 8373 
 8374 /*
 8375  * REMARKS:
 8376  * Pops a word from the stack.
 8377  * 
 8378  * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
 8379  */
 8380 static uint16_t 
 8381 pop_word(struct x86emu *emu)
 8382 {
 8383         uint16_t res;
 8384 
 8385         res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
 8386         emu->x86.R_SP += 2;
 8387         return res;
 8388 }
 8389 
 8390 /*
 8391  * REMARKS:
 8392  * Pops a long from the stack.
 8393  * 
 8394  * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
 8395  */
 8396 static uint32_t 
 8397 pop_long(struct x86emu *emu)
 8398 {
 8399         uint32_t res;
 8400 
 8401         res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
 8402         emu->x86.R_SP += 4;
 8403         return res;
 8404 }

Cache object: d9cc75d44d4a79790ab5eafa32761985


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.