LCOV - code coverage report
Current view: top level - dev/x86emu - x86emu.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 3828 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 340 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13