uboot/drivers/bios_emulator/x86emu/prim_ops.c
<<
>>
Prefs
   1/****************************************************************************
   2*
   3*                       Realmode X86 Emulator Library
   4*
   5*               Copyright (C) 1991-2004 SciTech Software, Inc.
   6*                    Copyright (C) David Mosberger-Tang
   7*                      Copyright (C) 1999 Egbert Eich
   8*
   9*  ========================================================================
  10*
  11*  Permission to use, copy, modify, distribute, and sell this software and
  12*  its documentation for any purpose is hereby granted without fee,
  13*  provided that the above copyright notice appear in all copies and that
  14*  both that copyright notice and this permission notice appear in
  15*  supporting documentation, and that the name of the authors not be used
  16*  in advertising or publicity pertaining to distribution of the software
  17*  without specific, written prior permission.  The authors makes no
  18*  representations about the suitability of this software for any purpose.
  19*  It is provided "as is" without express or implied warranty.
  20*
  21*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  22*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  23*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  25*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  26*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  27*  PERFORMANCE OF THIS SOFTWARE.
  28*
  29*  ========================================================================
  30*
  31* Language:     ANSI C
  32* Environment:  Any
  33* Developer:    Kendall Bennett
  34*
  35* Description:  This file contains the code to implement the primitive
  36*               machine operations used by the emulation code in ops.c
  37*
  38* Carry Chain Calculation
  39*
  40* This represents a somewhat expensive calculation which is
  41* apparently required to emulate the setting of the OF343364 and AF flag.
  42* The latter is not so important, but the former is.  The overflow
  43* flag is the XOR of the top two bits of the carry chain for an
  44* addition (similar for subtraction).  Since we do not want to
  45* simulate the addition in a bitwise manner, we try to calculate the
  46* carry chain given the two operands and the result.
  47*
  48* So, given the following table, which represents the addition of two
  49* bits, we can derive a formula for the carry chain.
  50*
  51* a   b   cin   r     cout
  52* 0   0   0     0     0
  53* 0   0   1     1     0
  54* 0   1   0     1     0
  55* 0   1   1     0     1
  56* 1   0   0     1     0
  57* 1   0   1     0     1
  58* 1   1   0     0     1
  59* 1   1   1     1     1
  60*
  61* Construction of table for cout:
  62*
  63* ab
  64* r  \  00   01   11  10
  65* |------------------
  66* 0  |   0    1    1   1
  67* 1  |   0    0    1   0
  68*
  69* By inspection, one gets:  cc = ab +  r'(a + b)
  70*
  71* That represents alot of operations, but NO CHOICE....
  72*
  73* Borrow Chain Calculation.
  74*
  75* The following table represents the subtraction of two bits, from
  76* which we can derive a formula for the borrow chain.
  77*
  78* a   b   bin   r     bout
  79* 0   0   0     0     0
  80* 0   0   1     1     1
  81* 0   1   0     1     1
  82* 0   1   1     0     1
  83* 1   0   0     1     0
  84* 1   0   1     0     0
  85* 1   1   0     0     0
  86* 1   1   1     1     1
  87*
  88* Construction of table for cout:
  89*
  90* ab
  91* r  \  00   01   11  10
  92* |------------------
  93* 0  |   0    1    0   0
  94* 1  |   1    1    1   0
  95*
  96* By inspection, one gets:  bc = a'b +  r(a' + b)
  97*
  98****************************************************************************/
  99
 100#include <common.h>
 101
 102#define PRIM_OPS_NO_REDEFINE_ASM
 103#include "x86emu/x86emui.h"
 104
 105/*------------------------- Global Variables ------------------------------*/
 106
 107static u32 x86emu_parity_tab[8] =
 108{
 109    0x96696996,
 110    0x69969669,
 111    0x69969669,
 112    0x96696996,
 113    0x69969669,
 114    0x96696996,
 115    0x96696996,
 116    0x69969669,
 117};
 118
 119#define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
 120#define XOR2(x)     (((x) ^ ((x)>>1)) & 0x1)
 121
 122/*----------------------------- Implementation ----------------------------*/
 123
 124
 125/*--------- Side effects helper functions -------*/
 126
 127/****************************************************************************
 128REMARKS:
 129implements side efects for byte operations that don't overflow
 130****************************************************************************/
 131
 132static void set_parity_flag(u32 res)
 133{
 134    CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
 135}
 136
 137static void set_szp_flags_8(u8 res)
 138{
 139    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
 140    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 141    set_parity_flag(res);
 142}
 143
 144static void set_szp_flags_16(u16 res)
 145{
 146    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
 147    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 148    set_parity_flag(res);
 149}
 150
 151static void set_szp_flags_32(u32 res)
 152{
 153    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
 154    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 155    set_parity_flag(res);
 156}
 157
 158static void no_carry_byte_side_eff(u8 res)
 159{
 160    CLEAR_FLAG(F_OF);
 161    CLEAR_FLAG(F_CF);
 162    CLEAR_FLAG(F_AF);
 163    set_szp_flags_8(res);
 164}
 165
 166static void no_carry_word_side_eff(u16 res)
 167{
 168    CLEAR_FLAG(F_OF);
 169    CLEAR_FLAG(F_CF);
 170    CLEAR_FLAG(F_AF);
 171    set_szp_flags_16(res);
 172}
 173
 174static void no_carry_long_side_eff(u32 res)
 175{
 176    CLEAR_FLAG(F_OF);
 177    CLEAR_FLAG(F_CF);
 178    CLEAR_FLAG(F_AF);
 179    set_szp_flags_32(res);
 180}
 181
 182static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
 183{
 184    u32 cc;
 185
 186    cc = (s & d) | ((~res) & (s | d));
 187    CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
 188    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
 189    if (set_carry) {
 190        CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
 191    }
 192}
 193
 194static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
 195{
 196    u32 bc;
 197
 198    bc = (res & (~d | s)) | (~d & s);
 199    CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
 200    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 201    if (set_carry) {
 202        CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
 203    }
 204}
 205
 206/****************************************************************************
 207REMARKS:
 208Implements the AAA instruction and side effects.
 209****************************************************************************/
 210u16 aaa_word(u16 d)
 211{
 212    u16 res;
 213    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
 214        d += 0x6;
 215        d += 0x100;
 216        SET_FLAG(F_AF);
 217        SET_FLAG(F_CF);
 218    } else {
 219        CLEAR_FLAG(F_CF);
 220        CLEAR_FLAG(F_AF);
 221    }
 222    res = (u16)(d & 0xFF0F);
 223    set_szp_flags_16(res);
 224    return res;
 225}
 226
 227/****************************************************************************
 228REMARKS:
 229Implements the AAA instruction and side effects.
 230****************************************************************************/
 231u16 aas_word(u16 d)
 232{
 233    u16 res;
 234    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
 235        d -= 0x6;
 236        d -= 0x100;
 237        SET_FLAG(F_AF);
 238        SET_FLAG(F_CF);
 239    } else {
 240        CLEAR_FLAG(F_CF);
 241        CLEAR_FLAG(F_AF);
 242    }
 243    res = (u16)(d & 0xFF0F);
 244    set_szp_flags_16(res);
 245    return res;
 246}
 247
 248/****************************************************************************
 249REMARKS:
 250Implements the AAD instruction and side effects.
 251****************************************************************************/
 252u16 aad_word(u16 d)
 253{
 254    u16 l;
 255    u8 hb, lb;
 256
 257    hb = (u8)((d >> 8) & 0xff);
 258    lb = (u8)((d & 0xff));
 259    l = (u16)((lb + 10 * hb) & 0xFF);
 260
 261    no_carry_byte_side_eff(l & 0xFF);
 262    return l;
 263}
 264
 265/****************************************************************************
 266REMARKS:
 267Implements the AAM instruction and side effects.
 268****************************************************************************/
 269u16 aam_word(u8 d)
 270{
 271    u16 h, l;
 272
 273    h = (u16)(d / 10);
 274    l = (u16)(d % 10);
 275    l |= (u16)(h << 8);
 276
 277    no_carry_byte_side_eff(l & 0xFF);
 278    return l;
 279}
 280
 281/****************************************************************************
 282REMARKS:
 283Implements the ADC instruction and side effects.
 284****************************************************************************/
 285u8 adc_byte(u8 d, u8 s)
 286{
 287    u32 res;   /* all operands in native machine order */
 288
 289    res = d + s;
 290    if (ACCESS_FLAG(F_CF)) res++;
 291
 292    set_szp_flags_8(res);
 293    calc_carry_chain(8,s,d,res,1);
 294
 295    return (u8)res;
 296}
 297
 298/****************************************************************************
 299REMARKS:
 300Implements the ADC instruction and side effects.
 301****************************************************************************/
 302u16 adc_word(u16 d, u16 s)
 303{
 304    u32 res;   /* all operands in native machine order */
 305
 306    res = d + s;
 307    if (ACCESS_FLAG(F_CF))
 308        res++;
 309
 310    set_szp_flags_16((u16)res);
 311    calc_carry_chain(16,s,d,res,1);
 312
 313    return (u16)res;
 314}
 315
 316/****************************************************************************
 317REMARKS:
 318Implements the ADC instruction and side effects.
 319****************************************************************************/
 320u32 adc_long(u32 d, u32 s)
 321{
 322    u32 lo;    /* all operands in native machine order */
 323    u32 hi;
 324    u32 res;
 325
 326    lo = (d & 0xFFFF) + (s & 0xFFFF);
 327    res = d + s;
 328
 329    if (ACCESS_FLAG(F_CF)) {
 330        lo++;
 331        res++;
 332    }
 333
 334    hi = (lo >> 16) + (d >> 16) + (s >> 16);
 335
 336    set_szp_flags_32(res);
 337    calc_carry_chain(32,s,d,res,0);
 338
 339    CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
 340
 341    return res;
 342}
 343
 344/****************************************************************************
 345REMARKS:
 346Implements the ADD instruction and side effects.
 347****************************************************************************/
 348u8 add_byte(u8 d, u8 s)
 349{
 350    u32 res;   /* all operands in native machine order */
 351
 352    res = d + s;
 353    set_szp_flags_8((u8)res);
 354    calc_carry_chain(8,s,d,res,1);
 355
 356    return (u8)res;
 357}
 358
 359/****************************************************************************
 360REMARKS:
 361Implements the ADD instruction and side effects.
 362****************************************************************************/
 363u16 add_word(u16 d, u16 s)
 364{
 365    u32 res;   /* all operands in native machine order */
 366
 367    res = d + s;
 368    set_szp_flags_16((u16)res);
 369    calc_carry_chain(16,s,d,res,1);
 370
 371    return (u16)res;
 372}
 373
 374/****************************************************************************
 375REMARKS:
 376Implements the ADD instruction and side effects.
 377****************************************************************************/
 378u32 add_long(u32 d, u32 s)
 379{
 380    u32 res;
 381
 382    res = d + s;
 383    set_szp_flags_32(res);
 384    calc_carry_chain(32,s,d,res,0);
 385
 386    CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
 387
 388    return res;
 389}
 390
 391/****************************************************************************
 392REMARKS:
 393Implements the AND instruction and side effects.
 394****************************************************************************/
 395u8 and_byte(u8 d, u8 s)
 396{
 397    u8 res;    /* all operands in native machine order */
 398
 399    res = d & s;
 400
 401    no_carry_byte_side_eff(res);
 402    return res;
 403}
 404
 405/****************************************************************************
 406REMARKS:
 407Implements the AND instruction and side effects.
 408****************************************************************************/
 409u16 and_word(u16 d, u16 s)
 410{
 411    u16 res;   /* all operands in native machine order */
 412
 413    res = d & s;
 414
 415    no_carry_word_side_eff(res);
 416    return res;
 417}
 418
 419/****************************************************************************
 420REMARKS:
 421Implements the AND instruction and side effects.
 422****************************************************************************/
 423u32 and_long(u32 d, u32 s)
 424{
 425    u32 res;   /* all operands in native machine order */
 426
 427    res = d & s;
 428    no_carry_long_side_eff(res);
 429    return res;
 430}
 431
 432/****************************************************************************
 433REMARKS:
 434Implements the CMP instruction and side effects.
 435****************************************************************************/
 436u8 cmp_byte(u8 d, u8 s)
 437{
 438    u32 res;   /* all operands in native machine order */
 439
 440    res = d - s;
 441    set_szp_flags_8((u8)res);
 442    calc_borrow_chain(8, d, s, res, 1);
 443
 444    return d;
 445}
 446
 447/****************************************************************************
 448REMARKS:
 449Implements the CMP instruction and side effects.
 450****************************************************************************/
 451u16 cmp_word(u16 d, u16 s)
 452{
 453    u32 res;   /* all operands in native machine order */
 454
 455    res = d - s;
 456    set_szp_flags_16((u16)res);
 457    calc_borrow_chain(16, d, s, res, 1);
 458
 459    return d;
 460}
 461
 462/****************************************************************************
 463REMARKS:
 464Implements the CMP instruction and side effects.
 465****************************************************************************/
 466u32 cmp_long(u32 d, u32 s)
 467{
 468    u32 res;   /* all operands in native machine order */
 469
 470    res = d - s;
 471    set_szp_flags_32(res);
 472    calc_borrow_chain(32, d, s, res, 1);
 473
 474    return d;
 475}
 476
 477/****************************************************************************
 478REMARKS:
 479Implements the DAA instruction and side effects.
 480****************************************************************************/
 481u8 daa_byte(u8 d)
 482{
 483    u32 res = d;
 484    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
 485        res += 6;
 486        SET_FLAG(F_AF);
 487    }
 488    if (res > 0x9F || ACCESS_FLAG(F_CF)) {
 489        res += 0x60;
 490        SET_FLAG(F_CF);
 491    }
 492    set_szp_flags_8((u8)res);
 493    return (u8)res;
 494}
 495
 496/****************************************************************************
 497REMARKS:
 498Implements the DAS instruction and side effects.
 499****************************************************************************/
 500u8 das_byte(u8 d)
 501{
 502    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
 503        d -= 6;
 504        SET_FLAG(F_AF);
 505    }
 506    if (d > 0x9F || ACCESS_FLAG(F_CF)) {
 507        d -= 0x60;
 508        SET_FLAG(F_CF);
 509    }
 510    set_szp_flags_8(d);
 511    return d;
 512}
 513
 514/****************************************************************************
 515REMARKS:
 516Implements the DEC instruction and side effects.
 517****************************************************************************/
 518u8 dec_byte(u8 d)
 519{
 520    u32 res;   /* all operands in native machine order */
 521
 522    res = d - 1;
 523    set_szp_flags_8((u8)res);
 524    calc_borrow_chain(8, d, 1, res, 0);
 525
 526    return (u8)res;
 527}
 528
 529/****************************************************************************
 530REMARKS:
 531Implements the DEC instruction and side effects.
 532****************************************************************************/
 533u16 dec_word(u16 d)
 534{
 535    u32 res;   /* all operands in native machine order */
 536
 537    res = d - 1;
 538    set_szp_flags_16((u16)res);
 539    calc_borrow_chain(16, d, 1, res, 0);
 540
 541    return (u16)res;
 542}
 543
 544/****************************************************************************
 545REMARKS:
 546Implements the DEC instruction and side effects.
 547****************************************************************************/
 548u32 dec_long(u32 d)
 549{
 550    u32 res;   /* all operands in native machine order */
 551
 552    res = d - 1;
 553
 554    set_szp_flags_32(res);
 555    calc_borrow_chain(32, d, 1, res, 0);
 556
 557    return res;
 558}
 559
 560/****************************************************************************
 561REMARKS:
 562Implements the INC instruction and side effects.
 563****************************************************************************/
 564u8 inc_byte(u8 d)
 565{
 566    u32 res;   /* all operands in native machine order */
 567
 568    res = d + 1;
 569    set_szp_flags_8((u8)res);
 570    calc_carry_chain(8, d, 1, res, 0);
 571
 572    return (u8)res;
 573}
 574
 575/****************************************************************************
 576REMARKS:
 577Implements the INC instruction and side effects.
 578****************************************************************************/
 579u16 inc_word(u16 d)
 580{
 581    u32 res;   /* all operands in native machine order */
 582
 583    res = d + 1;
 584    set_szp_flags_16((u16)res);
 585    calc_carry_chain(16, d, 1, res, 0);
 586
 587    return (u16)res;
 588}
 589
 590/****************************************************************************
 591REMARKS:
 592Implements the INC instruction and side effects.
 593****************************************************************************/
 594u32 inc_long(u32 d)
 595{
 596    u32 res;   /* all operands in native machine order */
 597
 598    res = d + 1;
 599    set_szp_flags_32(res);
 600    calc_carry_chain(32, d, 1, res, 0);
 601
 602    return res;
 603}
 604
 605/****************************************************************************
 606REMARKS:
 607Implements the OR instruction and side effects.
 608****************************************************************************/
 609u8 or_byte(u8 d, u8 s)
 610{
 611    u8 res;    /* all operands in native machine order */
 612
 613    res = d | s;
 614    no_carry_byte_side_eff(res);
 615
 616    return res;
 617}
 618
 619/****************************************************************************
 620REMARKS:
 621Implements the OR instruction and side effects.
 622****************************************************************************/
 623u16 or_word(u16 d, u16 s)
 624{
 625    u16 res;   /* all operands in native machine order */
 626
 627    res = d | s;
 628    no_carry_word_side_eff(res);
 629    return res;
 630}
 631
 632/****************************************************************************
 633REMARKS:
 634Implements the OR instruction and side effects.
 635****************************************************************************/
 636u32 or_long(u32 d, u32 s)
 637{
 638    u32 res;   /* all operands in native machine order */
 639
 640    res = d | s;
 641    no_carry_long_side_eff(res);
 642    return res;
 643}
 644
 645/****************************************************************************
 646REMARKS:
 647Implements the OR instruction and side effects.
 648****************************************************************************/
 649u8 neg_byte(u8 s)
 650{
 651    u8 res;
 652
 653    CONDITIONAL_SET_FLAG(s != 0, F_CF);
 654    res = (u8)-s;
 655    set_szp_flags_8(res);
 656    calc_borrow_chain(8, 0, s, res, 0);
 657
 658    return res;
 659}
 660
 661/****************************************************************************
 662REMARKS:
 663Implements the OR instruction and side effects.
 664****************************************************************************/
 665u16 neg_word(u16 s)
 666{
 667    u16 res;
 668
 669    CONDITIONAL_SET_FLAG(s != 0, F_CF);
 670    res = (u16)-s;
 671    set_szp_flags_16((u16)res);
 672    calc_borrow_chain(16, 0, s, res, 0);
 673
 674    return res;
 675}
 676
 677/****************************************************************************
 678REMARKS:
 679Implements the OR instruction and side effects.
 680****************************************************************************/
 681u32 neg_long(u32 s)
 682{
 683    u32 res;
 684
 685    CONDITIONAL_SET_FLAG(s != 0, F_CF);
 686    res = (u32)-s;
 687    set_szp_flags_32(res);
 688    calc_borrow_chain(32, 0, s, res, 0);
 689
 690    return res;
 691}
 692
 693/****************************************************************************
 694REMARKS:
 695Implements the NOT instruction and side effects.
 696****************************************************************************/
 697u8 not_byte(u8 s)
 698{
 699    return ~s;
 700}
 701
 702/****************************************************************************
 703REMARKS:
 704Implements the NOT instruction and side effects.
 705****************************************************************************/
 706u16 not_word(u16 s)
 707{
 708    return ~s;
 709}
 710
 711/****************************************************************************
 712REMARKS:
 713Implements the NOT instruction and side effects.
 714****************************************************************************/
 715u32 not_long(u32 s)
 716{
 717    return ~s;
 718}
 719
 720/****************************************************************************
 721REMARKS:
 722Implements the RCL instruction and side effects.
 723****************************************************************************/
 724u8 rcl_byte(u8 d, u8 s)
 725{
 726    unsigned int res, cnt, mask, cf;
 727
 728    /* s is the rotate distance.  It varies from 0 - 8. */
 729    /* have
 730
 731       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
 732
 733       want to rotate through the carry by "s" bits.  We could
 734       loop, but that's inefficient.  So the width is 9,
 735       and we split into three parts:
 736
 737       The new carry flag   (was B_n)
 738       the stuff in B_n-1 .. B_0
 739       the stuff in B_7 .. B_n+1
 740
 741       The new rotate is done mod 9, and given this,
 742       for a rotation of n bits (mod 9) the new carry flag is
 743       then located n bits from the MSB.  The low part is
 744       then shifted up cnt bits, and the high part is or'd
 745       in.  Using CAPS for new values, and lowercase for the
 746       original values, this can be expressed as:
 747
 748       IF n > 0
 749       1) CF <-  b_(8-n)
 750       2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
 751       3) B_(n-1) <- cf
 752       4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
 753     */
 754    res = d;
 755    if ((cnt = s % 9) != 0) {
 756        /* extract the new CARRY FLAG. */
 757        /* CF <-  b_(8-n)             */
 758        cf = (d >> (8 - cnt)) & 0x1;
 759
 760        /* get the low stuff which rotated
 761           into the range B_7 .. B_cnt */
 762        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
 763        /* note that the right hand side done by the mask */
 764        res = (d << cnt) & 0xff;
 765
 766        /* now the high stuff which rotated around
 767           into the positions B_cnt-2 .. B_0 */
 768        /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
 769        /* shift it downward, 7-(n-2) = 9-n positions.
 770           and mask off the result before or'ing in.
 771         */
 772        mask = (1 << (cnt - 1)) - 1;
 773        res |= (d >> (9 - cnt)) & mask;
 774
 775        /* if the carry flag was set, or it in.  */
 776        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 777            /*  B_(n-1) <- cf */
 778            res |= 1 << (cnt - 1);
 779        }
 780        /* set the new carry flag, based on the variable "cf" */
 781        CONDITIONAL_SET_FLAG(cf, F_CF);
 782        /* OVERFLOW is set *IFF* cnt==1, then it is the
 783           xor of CF and the most significant bit.  Blecck. */
 784        /* parenthesized this expression since it appears to
 785           be causing OF to be misset */
 786        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
 787                             F_OF);
 788
 789    }
 790    return (u8)res;
 791}
 792
 793/****************************************************************************
 794REMARKS:
 795Implements the RCL instruction and side effects.
 796****************************************************************************/
 797u16 rcl_word(u16 d, u8 s)
 798{
 799    unsigned int res, cnt, mask, cf;
 800
 801    res = d;
 802    if ((cnt = s % 17) != 0) {
 803        cf = (d >> (16 - cnt)) & 0x1;
 804        res = (d << cnt) & 0xffff;
 805        mask = (1 << (cnt - 1)) - 1;
 806        res |= (d >> (17 - cnt)) & mask;
 807        if (ACCESS_FLAG(F_CF)) {
 808            res |= 1 << (cnt - 1);
 809        }
 810        CONDITIONAL_SET_FLAG(cf, F_CF);
 811        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
 812                             F_OF);
 813    }
 814    return (u16)res;
 815}
 816
 817/****************************************************************************
 818REMARKS:
 819Implements the RCL instruction and side effects.
 820****************************************************************************/
 821u32 rcl_long(u32 d, u8 s)
 822{
 823    u32 res, cnt, mask, cf;
 824
 825    res = d;
 826    if ((cnt = s % 33) != 0) {
 827        cf = (d >> (32 - cnt)) & 0x1;
 828        res = (d << cnt) & 0xffffffff;
 829        mask = (1 << (cnt - 1)) - 1;
 830        res |= (d >> (33 - cnt)) & mask;
 831        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 832            res |= 1 << (cnt - 1);
 833        }
 834        CONDITIONAL_SET_FLAG(cf, F_CF);
 835        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
 836                             F_OF);
 837    }
 838    return res;
 839}
 840
 841/****************************************************************************
 842REMARKS:
 843Implements the RCR instruction and side effects.
 844****************************************************************************/
 845u8 rcr_byte(u8 d, u8 s)
 846{
 847    u32 res, cnt;
 848    u32 mask, cf, ocf = 0;
 849
 850    /* rotate right through carry */
 851    /*
 852       s is the rotate distance.  It varies from 0 - 8.
 853       d is the byte object rotated.
 854
 855       have
 856
 857       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
 858
 859       The new rotate is done mod 9, and given this,
 860       for a rotation of n bits (mod 9) the new carry flag is
 861       then located n bits from the LSB.  The low part is
 862       then shifted up cnt bits, and the high part is or'd
 863       in.  Using CAPS for new values, and lowercase for the
 864       original values, this can be expressed as:
 865
 866       IF n > 0
 867       1) CF <-  b_(n-1)
 868       2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
 869       3) B_(8-n) <- cf
 870       4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
 871     */
 872    res = d;
 873    if ((cnt = s % 9) != 0) {
 874        /* extract the new CARRY FLAG. */
 875        /* CF <-  b_(n-1)              */
 876        if (cnt == 1) {
 877            cf = d & 0x1;
 878            /* note hackery here.  Access_flag(..) evaluates to either
 879               0 if flag not set
 880               non-zero if flag is set.
 881               doing access_flag(..) != 0 casts that into either
 882               0..1 in any representation of the flags register
 883               (i.e. packed bit array or unpacked.)
 884             */
 885            ocf = ACCESS_FLAG(F_CF) != 0;
 886        } else
 887            cf = (d >> (cnt - 1)) & 0x1;
 888
 889        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
 890        /* note that the right hand side done by the mask
 891           This is effectively done by shifting the
 892           object to the right.  The result must be masked,
 893           in case the object came in and was treated
 894           as a negative number.  Needed??? */
 895
 896        mask = (1 << (8 - cnt)) - 1;
 897        res = (d >> cnt) & mask;
 898
 899        /* now the high stuff which rotated around
 900           into the positions B_cnt-2 .. B_0 */
 901        /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
 902        /* shift it downward, 7-(n-2) = 9-n positions.
 903           and mask off the result before or'ing in.
 904         */
 905        res |= (d << (9 - cnt));
 906
 907        /* if the carry flag was set, or it in.  */
 908        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 909            /*  B_(8-n) <- cf */
 910            res |= 1 << (8 - cnt);
 911        }
 912        /* set the new carry flag, based on the variable "cf" */
 913        CONDITIONAL_SET_FLAG(cf, F_CF);
 914        /* OVERFLOW is set *IFF* cnt==1, then it is the
 915           xor of CF and the most significant bit.  Blecck. */
 916        /* parenthesized... */
 917        if (cnt == 1) {
 918            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
 919                                 F_OF);
 920        }
 921    }
 922    return (u8)res;
 923}
 924
 925/****************************************************************************
 926REMARKS:
 927Implements the RCR instruction and side effects.
 928****************************************************************************/
 929u16 rcr_word(u16 d, u8 s)
 930{
 931    u32 res, cnt;
 932    u32 mask, cf, ocf = 0;
 933
 934    /* rotate right through carry */
 935    res = d;
 936    if ((cnt = s % 17) != 0) {
 937        if (cnt == 1) {
 938            cf = d & 0x1;
 939            ocf = ACCESS_FLAG(F_CF) != 0;
 940        } else
 941            cf = (d >> (cnt - 1)) & 0x1;
 942        mask = (1 << (16 - cnt)) - 1;
 943        res = (d >> cnt) & mask;
 944        res |= (d << (17 - cnt));
 945        if (ACCESS_FLAG(F_CF)) {
 946            res |= 1 << (16 - cnt);
 947        }
 948        CONDITIONAL_SET_FLAG(cf, F_CF);
 949        if (cnt == 1) {
 950            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
 951                                 F_OF);
 952        }
 953    }
 954    return (u16)res;
 955}
 956
 957/****************************************************************************
 958REMARKS:
 959Implements the RCR instruction and side effects.
 960****************************************************************************/
 961u32 rcr_long(u32 d, u8 s)
 962{
 963    u32 res, cnt;
 964    u32 mask, cf, ocf = 0;
 965
 966    /* rotate right through carry */
 967    res = d;
 968    if ((cnt = s % 33) != 0) {
 969        if (cnt == 1) {
 970            cf = d & 0x1;
 971            ocf = ACCESS_FLAG(F_CF) != 0;
 972        } else
 973            cf = (d >> (cnt - 1)) & 0x1;
 974        mask = (1 << (32 - cnt)) - 1;
 975        res = (d >> cnt) & mask;
 976        if (cnt != 1)
 977            res |= (d << (33 - cnt));
 978        if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
 979            res |= 1 << (32 - cnt);
 980        }
 981        CONDITIONAL_SET_FLAG(cf, F_CF);
 982        if (cnt == 1) {
 983            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
 984                                 F_OF);
 985        }
 986    }
 987    return res;
 988}
 989
 990/****************************************************************************
 991REMARKS:
 992Implements the ROL instruction and side effects.
 993****************************************************************************/
 994u8 rol_byte(u8 d, u8 s)
 995{
 996    unsigned int res, cnt, mask;
 997
 998    /* rotate left */
 999    /*
1000       s is the rotate distance.  It varies from 0 - 8.
1001       d is the byte object rotated.
1002
1003       have
1004
1005       CF  B_7 ... B_0
1006
1007       The new rotate is done mod 8.
1008       Much simpler than the "rcl" or "rcr" operations.
1009
1010       IF n > 0
1011       1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
1012       2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
1013     */
1014    res = d;
1015    if ((cnt = s % 8) != 0) {
1016        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1017        res = (d << cnt);
1018
1019        /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1020        mask = (1 << cnt) - 1;
1021        res |= (d >> (8 - cnt)) & mask;
1022
1023        /* set the new carry flag, Note that it is the low order
1024           bit of the result!!!                               */
1025        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1026        /* OVERFLOW is set *IFF* s==1, then it is the
1027           xor of CF and the most significant bit.  Blecck. */
1028        CONDITIONAL_SET_FLAG(s == 1 &&
1029                             XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1030                             F_OF);
1031    } if (s != 0) {
1032        /* set the new carry flag, Note that it is the low order
1033           bit of the result!!!                               */
1034        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1035    }
1036    return (u8)res;
1037}
1038
1039/****************************************************************************
1040REMARKS:
1041Implements the ROL instruction and side effects.
1042****************************************************************************/
1043u16 rol_word(u16 d, u8 s)
1044{
1045    unsigned int res, cnt, mask;
1046
1047    res = d;
1048    if ((cnt = s % 16) != 0) {
1049        res = (d << cnt);
1050        mask = (1 << cnt) - 1;
1051        res |= (d >> (16 - cnt)) & mask;
1052        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1053        CONDITIONAL_SET_FLAG(s == 1 &&
1054                             XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1055                             F_OF);
1056    } if (s != 0) {
1057        /* set the new carry flag, Note that it is the low order
1058           bit of the result!!!                               */
1059        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1060    }
1061    return (u16)res;
1062}
1063
1064/****************************************************************************
1065REMARKS:
1066Implements the ROL instruction and side effects.
1067****************************************************************************/
1068u32 rol_long(u32 d, u8 s)
1069{
1070    u32 res, cnt, mask;
1071
1072    res = d;
1073    if ((cnt = s % 32) != 0) {
1074        res = (d << cnt);
1075        mask = (1 << cnt) - 1;
1076        res |= (d >> (32 - cnt)) & mask;
1077        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1078        CONDITIONAL_SET_FLAG(s == 1 &&
1079                             XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1080                             F_OF);
1081    } if (s != 0) {
1082        /* set the new carry flag, Note that it is the low order
1083           bit of the result!!!                               */
1084        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1085    }
1086    return res;
1087}
1088
1089/****************************************************************************
1090REMARKS:
1091Implements the ROR instruction and side effects.
1092****************************************************************************/
1093u8 ror_byte(u8 d, u8 s)
1094{
1095    unsigned int res, cnt, mask;
1096
1097    /* rotate right */
1098    /*
1099       s is the rotate distance.  It varies from 0 - 8.
1100       d is the byte object rotated.
1101
1102       have
1103
1104       B_7 ... B_0
1105
1106       The rotate is done mod 8.
1107
1108       IF n > 0
1109       1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
1110       2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
1111     */
1112    res = d;
1113    if ((cnt = s % 8) != 0) {           /* not a typo, do nada if cnt==0 */
1114        /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
1115        res = (d << (8 - cnt));
1116
1117        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
1118        mask = (1 << (8 - cnt)) - 1;
1119        res |= (d >> (cnt)) & mask;
1120
1121        /* set the new carry flag, Note that it is the low order
1122           bit of the result!!!                               */
1123        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1124        /* OVERFLOW is set *IFF* s==1, then it is the
1125           xor of the two most significant bits.  Blecck. */
1126        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1127    } else if (s != 0) {
1128        /* set the new carry flag, Note that it is the low order
1129           bit of the result!!!                               */
1130        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1131    }
1132    return (u8)res;
1133}
1134
1135/****************************************************************************
1136REMARKS:
1137Implements the ROR instruction and side effects.
1138****************************************************************************/
1139u16 ror_word(u16 d, u8 s)
1140{
1141    unsigned int res, cnt, mask;
1142
1143    res = d;
1144    if ((cnt = s % 16) != 0) {
1145        res = (d << (16 - cnt));
1146        mask = (1 << (16 - cnt)) - 1;
1147        res |= (d >> (cnt)) & mask;
1148        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1149        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1150    } else if (s != 0) {
1151        /* set the new carry flag, Note that it is the low order
1152           bit of the result!!!                               */
1153        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1154    }
1155    return (u16)res;
1156}
1157
1158/****************************************************************************
1159REMARKS:
1160Implements the ROR instruction and side effects.
1161****************************************************************************/
1162u32 ror_long(u32 d, u8 s)
1163{
1164    u32 res, cnt, mask;
1165
1166    res = d;
1167    if ((cnt = s % 32) != 0) {
1168        res = (d << (32 - cnt));
1169        mask = (1 << (32 - cnt)) - 1;
1170        res |= (d >> (cnt)) & mask;
1171        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1172        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1173    } else if (s != 0) {
1174        /* set the new carry flag, Note that it is the low order
1175           bit of the result!!!                               */
1176        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1177    }
1178    return res;
1179}
1180
1181/****************************************************************************
1182REMARKS:
1183Implements the SHL instruction and side effects.
1184****************************************************************************/
1185u8 shl_byte(u8 d, u8 s)
1186{
1187    unsigned int cnt, res, cf;
1188
1189    if (s < 8) {
1190        cnt = s % 8;
1191
1192        /* last bit shifted out goes into carry flag */
1193        if (cnt > 0) {
1194            res = d << cnt;
1195            cf = d & (1 << (8 - cnt));
1196            CONDITIONAL_SET_FLAG(cf, F_CF);
1197            set_szp_flags_8((u8)res);
1198        } else {
1199            res = (u8) d;
1200        }
1201
1202        if (cnt == 1) {
1203            /* Needs simplification. */
1204            CONDITIONAL_SET_FLAG(
1205                                    (((res & 0x80) == 0x80) ^
1206                                     (ACCESS_FLAG(F_CF) != 0)),
1207            /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1208                                    F_OF);
1209        } else {
1210            CLEAR_FLAG(F_OF);
1211        }
1212    } else {
1213        res = 0;
1214        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1215        CLEAR_FLAG(F_OF);
1216        CLEAR_FLAG(F_SF);
1217        SET_FLAG(F_PF);
1218        SET_FLAG(F_ZF);
1219    }
1220    return (u8)res;
1221}
1222
1223/****************************************************************************
1224REMARKS:
1225Implements the SHL instruction and side effects.
1226****************************************************************************/
1227u16 shl_word(u16 d, u8 s)
1228{
1229    unsigned int cnt, res, cf;
1230
1231    if (s < 16) {
1232        cnt = s % 16;
1233        if (cnt > 0) {
1234            res = d << cnt;
1235            cf = d & (1 << (16 - cnt));
1236            CONDITIONAL_SET_FLAG(cf, F_CF);
1237            set_szp_flags_16((u16)res);
1238        } else {
1239            res = (u16) d;
1240        }
1241
1242        if (cnt == 1) {
1243            CONDITIONAL_SET_FLAG(
1244                                    (((res & 0x8000) == 0x8000) ^
1245                                     (ACCESS_FLAG(F_CF) != 0)),
1246                                    F_OF);
1247        } else {
1248            CLEAR_FLAG(F_OF);
1249        }
1250    } else {
1251        res = 0;
1252        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1253        CLEAR_FLAG(F_OF);
1254        CLEAR_FLAG(F_SF);
1255        SET_FLAG(F_PF);
1256        SET_FLAG(F_ZF);
1257    }
1258    return (u16)res;
1259}
1260
1261/****************************************************************************
1262REMARKS:
1263Implements the SHL instruction and side effects.
1264****************************************************************************/
1265u32 shl_long(u32 d, u8 s)
1266{
1267    unsigned int cnt, res, cf;
1268
1269    if (s < 32) {
1270        cnt = s % 32;
1271        if (cnt > 0) {
1272            res = d << cnt;
1273            cf = d & (1 << (32 - cnt));
1274            CONDITIONAL_SET_FLAG(cf, F_CF);
1275            set_szp_flags_32((u32)res);
1276        } else {
1277            res = d;
1278        }
1279        if (cnt == 1) {
1280            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1281                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1282        } else {
1283            CLEAR_FLAG(F_OF);
1284        }
1285    } else {
1286        res = 0;
1287        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1288        CLEAR_FLAG(F_OF);
1289        CLEAR_FLAG(F_SF);
1290        SET_FLAG(F_PF);
1291        SET_FLAG(F_ZF);
1292    }
1293    return res;
1294}
1295
1296/****************************************************************************
1297REMARKS:
1298Implements the SHR instruction and side effects.
1299****************************************************************************/
1300u8 shr_byte(u8 d, u8 s)
1301{
1302    unsigned int cnt, res, cf;
1303
1304    if (s < 8) {
1305        cnt = s % 8;
1306        if (cnt > 0) {
1307            cf = d & (1 << (cnt - 1));
1308            res = d >> cnt;
1309            CONDITIONAL_SET_FLAG(cf, F_CF);
1310            set_szp_flags_8((u8)res);
1311        } else {
1312            res = (u8) d;
1313        }
1314
1315        if (cnt == 1) {
1316            CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1317        } else {
1318            CLEAR_FLAG(F_OF);
1319        }
1320    } else {
1321        res = 0;
1322        CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1323        CLEAR_FLAG(F_OF);
1324        CLEAR_FLAG(F_SF);
1325        SET_FLAG(F_PF);
1326        SET_FLAG(F_ZF);
1327    }
1328    return (u8)res;
1329}
1330
1331/****************************************************************************
1332REMARKS:
1333Implements the SHR instruction and side effects.
1334****************************************************************************/
1335u16 shr_word(u16 d, u8 s)
1336{
1337    unsigned int cnt, res, cf;
1338
1339    if (s < 16) {
1340        cnt = s % 16;
1341        if (cnt > 0) {
1342            cf = d & (1 << (cnt - 1));
1343            res = d >> cnt;
1344            CONDITIONAL_SET_FLAG(cf, F_CF);
1345            set_szp_flags_16((u16)res);
1346        } else {
1347            res = d;
1348        }
1349
1350        if (cnt == 1) {
1351            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1352        } else {
1353            CLEAR_FLAG(F_OF);
1354        }
1355    } else {
1356        res = 0;
1357        CLEAR_FLAG(F_CF);
1358        CLEAR_FLAG(F_OF);
1359        SET_FLAG(F_ZF);
1360        CLEAR_FLAG(F_SF);
1361        CLEAR_FLAG(F_PF);
1362    }
1363    return (u16)res;
1364}
1365
1366/****************************************************************************
1367REMARKS:
1368Implements the SHR instruction and side effects.
1369****************************************************************************/
1370u32 shr_long(u32 d, u8 s)
1371{
1372    unsigned int cnt, res, cf;
1373
1374    if (s < 32) {
1375        cnt = s % 32;
1376        if (cnt > 0) {
1377            cf = d & (1 << (cnt - 1));
1378            res = d >> cnt;
1379            CONDITIONAL_SET_FLAG(cf, F_CF);
1380            set_szp_flags_32((u32)res);
1381        } else {
1382            res = d;
1383        }
1384        if (cnt == 1) {
1385            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1386        } else {
1387            CLEAR_FLAG(F_OF);
1388        }
1389    } else {
1390        res = 0;
1391        CLEAR_FLAG(F_CF);
1392        CLEAR_FLAG(F_OF);
1393        SET_FLAG(F_ZF);
1394        CLEAR_FLAG(F_SF);
1395        CLEAR_FLAG(F_PF);
1396    }
1397    return res;
1398}
1399
1400/****************************************************************************
1401REMARKS:
1402Implements the SAR instruction and side effects.
1403****************************************************************************/
1404u8 sar_byte(u8 d, u8 s)
1405{
1406    unsigned int cnt, res, cf, mask, sf;
1407
1408    res = d;
1409    sf = d & 0x80;
1410    cnt = s % 8;
1411    if (cnt > 0 && cnt < 8) {
1412        mask = (1 << (8 - cnt)) - 1;
1413        cf = d & (1 << (cnt - 1));
1414        res = (d >> cnt) & mask;
1415        CONDITIONAL_SET_FLAG(cf, F_CF);
1416        if (sf) {
1417            res |= ~mask;
1418        }
1419        set_szp_flags_8((u8)res);
1420    } else if (cnt >= 8) {
1421        if (sf) {
1422            res = 0xff;
1423            SET_FLAG(F_CF);
1424            CLEAR_FLAG(F_ZF);
1425            SET_FLAG(F_SF);
1426            SET_FLAG(F_PF);
1427        } else {
1428            res = 0;
1429            CLEAR_FLAG(F_CF);
1430            SET_FLAG(F_ZF);
1431            CLEAR_FLAG(F_SF);
1432            CLEAR_FLAG(F_PF);
1433        }
1434    }
1435    return (u8)res;
1436}
1437
1438/****************************************************************************
1439REMARKS:
1440Implements the SAR instruction and side effects.
1441****************************************************************************/
1442u16 sar_word(u16 d, u8 s)
1443{
1444    unsigned int cnt, res, cf, mask, sf;
1445
1446    sf = d & 0x8000;
1447    cnt = s % 16;
1448    res = d;
1449    if (cnt > 0 && cnt < 16) {
1450        mask = (1 << (16 - cnt)) - 1;
1451        cf = d & (1 << (cnt - 1));
1452        res = (d >> cnt) & mask;
1453        CONDITIONAL_SET_FLAG(cf, F_CF);
1454        if (sf) {
1455            res |= ~mask;
1456        }
1457        set_szp_flags_16((u16)res);
1458    } else if (cnt >= 16) {
1459        if (sf) {
1460            res = 0xffff;
1461            SET_FLAG(F_CF);
1462            CLEAR_FLAG(F_ZF);
1463            SET_FLAG(F_SF);
1464            SET_FLAG(F_PF);
1465        } else {
1466            res = 0;
1467            CLEAR_FLAG(F_CF);
1468            SET_FLAG(F_ZF);
1469            CLEAR_FLAG(F_SF);
1470            CLEAR_FLAG(F_PF);
1471        }
1472    }
1473    return (u16)res;
1474}
1475
1476/****************************************************************************
1477REMARKS:
1478Implements the SAR instruction and side effects.
1479****************************************************************************/
1480u32 sar_long(u32 d, u8 s)
1481{
1482    u32 cnt, res, cf, mask, sf;
1483
1484    sf = d & 0x80000000;
1485    cnt = s % 32;
1486    res = d;
1487    if (cnt > 0 && cnt < 32) {
1488        mask = (1 << (32 - cnt)) - 1;
1489        cf = d & (1 << (cnt - 1));
1490        res = (d >> cnt) & mask;
1491        CONDITIONAL_SET_FLAG(cf, F_CF);
1492        if (sf) {
1493            res |= ~mask;
1494        }
1495        set_szp_flags_32(res);
1496    } else if (cnt >= 32) {
1497        if (sf) {
1498            res = 0xffffffff;
1499            SET_FLAG(F_CF);
1500            CLEAR_FLAG(F_ZF);
1501            SET_FLAG(F_SF);
1502            SET_FLAG(F_PF);
1503        } else {
1504            res = 0;
1505            CLEAR_FLAG(F_CF);
1506            SET_FLAG(F_ZF);
1507            CLEAR_FLAG(F_SF);
1508            CLEAR_FLAG(F_PF);
1509        }
1510    }
1511    return res;
1512}
1513
1514/****************************************************************************
1515REMARKS:
1516Implements the SHLD instruction and side effects.
1517****************************************************************************/
1518u16 shld_word (u16 d, u16 fill, u8 s)
1519{
1520    unsigned int cnt, res, cf;
1521
1522    if (s < 16) {
1523        cnt = s % 16;
1524        if (cnt > 0) {
1525            res = (d << cnt) | (fill >> (16-cnt));
1526            cf = d & (1 << (16 - cnt));
1527            CONDITIONAL_SET_FLAG(cf, F_CF);
1528            set_szp_flags_16((u16)res);
1529        } else {
1530            res = d;
1531        }
1532        if (cnt == 1) {
1533            CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1534                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1535        } else {
1536            CLEAR_FLAG(F_OF);
1537        }
1538    } else {
1539        res = 0;
1540        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1541        CLEAR_FLAG(F_OF);
1542        CLEAR_FLAG(F_SF);
1543        SET_FLAG(F_PF);
1544        SET_FLAG(F_ZF);
1545    }
1546    return (u16)res;
1547}
1548
1549/****************************************************************************
1550REMARKS:
1551Implements the SHLD instruction and side effects.
1552****************************************************************************/
1553u32 shld_long (u32 d, u32 fill, u8 s)
1554{
1555    unsigned int cnt, res, cf;
1556
1557    if (s < 32) {
1558        cnt = s % 32;
1559        if (cnt > 0) {
1560            res = (d << cnt) | (fill >> (32-cnt));
1561            cf = d & (1 << (32 - cnt));
1562            CONDITIONAL_SET_FLAG(cf, F_CF);
1563            set_szp_flags_32((u32)res);
1564        } else {
1565            res = d;
1566        }
1567        if (cnt == 1) {
1568            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1569                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1570        } else {
1571            CLEAR_FLAG(F_OF);
1572        }
1573    } else {
1574        res = 0;
1575        CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1576        CLEAR_FLAG(F_OF);
1577        CLEAR_FLAG(F_SF);
1578        SET_FLAG(F_PF);
1579        SET_FLAG(F_ZF);
1580    }
1581    return res;
1582}
1583
1584/****************************************************************************
1585REMARKS:
1586Implements the SHRD instruction and side effects.
1587****************************************************************************/
1588u16 shrd_word (u16 d, u16 fill, u8 s)
1589{
1590    unsigned int cnt, res, cf;
1591
1592    if (s < 16) {
1593        cnt = s % 16;
1594        if (cnt > 0) {
1595            cf = d & (1 << (cnt - 1));
1596            res = (d >> cnt) | (fill << (16 - cnt));
1597            CONDITIONAL_SET_FLAG(cf, F_CF);
1598            set_szp_flags_16((u16)res);
1599        } else {
1600            res = d;
1601        }
1602
1603        if (cnt == 1) {
1604            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1605        } else {
1606            CLEAR_FLAG(F_OF);
1607        }
1608    } else {
1609        res = 0;
1610        CLEAR_FLAG(F_CF);
1611        CLEAR_FLAG(F_OF);
1612        SET_FLAG(F_ZF);
1613        CLEAR_FLAG(F_SF);
1614        CLEAR_FLAG(F_PF);
1615    }
1616    return (u16)res;
1617}
1618
1619/****************************************************************************
1620REMARKS:
1621Implements the SHRD instruction and side effects.
1622****************************************************************************/
1623u32 shrd_long (u32 d, u32 fill, u8 s)
1624{
1625    unsigned int cnt, res, cf;
1626
1627    if (s < 32) {
1628        cnt = s % 32;
1629        if (cnt > 0) {
1630            cf = d & (1 << (cnt - 1));
1631            res = (d >> cnt) | (fill << (32 - cnt));
1632            CONDITIONAL_SET_FLAG(cf, F_CF);
1633            set_szp_flags_32((u32)res);
1634        } else {
1635            res = d;
1636        }
1637        if (cnt == 1) {
1638            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1639        } else {
1640            CLEAR_FLAG(F_OF);
1641        }
1642    } else {
1643        res = 0;
1644        CLEAR_FLAG(F_CF);
1645        CLEAR_FLAG(F_OF);
1646        SET_FLAG(F_ZF);
1647        CLEAR_FLAG(F_SF);
1648        CLEAR_FLAG(F_PF);
1649    }
1650    return res;
1651}
1652
1653/****************************************************************************
1654REMARKS:
1655Implements the SBB instruction and side effects.
1656****************************************************************************/
1657u8 sbb_byte(u8 d, u8 s)
1658{
1659    u32 res;   /* all operands in native machine order */
1660    u32 bc;
1661
1662    if (ACCESS_FLAG(F_CF))
1663        res = d - s - 1;
1664    else
1665        res = d - s;
1666    set_szp_flags_8((u8)res);
1667
1668    /* calculate the borrow chain.  See note at top */
1669    bc = (res & (~d | s)) | (~d & s);
1670    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1671    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1672    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1673    return (u8)res;
1674}
1675
1676/****************************************************************************
1677REMARKS:
1678Implements the SBB instruction and side effects.
1679****************************************************************************/
1680u16 sbb_word(u16 d, u16 s)
1681{
1682    u32 res;   /* all operands in native machine order */
1683    u32 bc;
1684
1685    if (ACCESS_FLAG(F_CF))
1686        res = d - s - 1;
1687    else
1688        res = d - s;
1689    set_szp_flags_16((u16)res);
1690
1691    /* calculate the borrow chain.  See note at top */
1692    bc = (res & (~d | s)) | (~d & s);
1693    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1694    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1695    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1696    return (u16)res;
1697}
1698
1699/****************************************************************************
1700REMARKS:
1701Implements the SBB instruction and side effects.
1702****************************************************************************/
1703u32 sbb_long(u32 d, u32 s)
1704{
1705    u32 res;   /* all operands in native machine order */
1706    u32 bc;
1707
1708    if (ACCESS_FLAG(F_CF))
1709        res = d - s - 1;
1710    else
1711        res = d - s;
1712
1713    set_szp_flags_32(res);
1714
1715    /* calculate the borrow chain.  See note at top */
1716    bc = (res & (~d | s)) | (~d & s);
1717    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1718    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1719    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1720    return res;
1721}
1722
1723/****************************************************************************
1724REMARKS:
1725Implements the SUB instruction and side effects.
1726****************************************************************************/
1727u8 sub_byte(u8 d, u8 s)
1728{
1729    u32 res;   /* all operands in native machine order */
1730    u32 bc;
1731
1732    res = d - s;
1733    set_szp_flags_8((u8)res);
1734
1735    /* calculate the borrow chain.  See note at top */
1736    bc = (res & (~d | s)) | (~d & s);
1737    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1738    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1739    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1740    return (u8)res;
1741}
1742
1743/****************************************************************************
1744REMARKS:
1745Implements the SUB instruction and side effects.
1746****************************************************************************/
1747u16 sub_word(u16 d, u16 s)
1748{
1749    u32 res;   /* all operands in native machine order */
1750    u32 bc;
1751
1752    res = d - s;
1753    set_szp_flags_16((u16)res);
1754
1755    /* calculate the borrow chain.  See note at top */
1756    bc = (res & (~d | s)) | (~d & s);
1757    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1758    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1759    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1760    return (u16)res;
1761}
1762
1763/****************************************************************************
1764REMARKS:
1765Implements the SUB instruction and side effects.
1766****************************************************************************/
1767u32 sub_long(u32 d, u32 s)
1768{
1769    u32 res;   /* all operands in native machine order */
1770    u32 bc;
1771
1772    res = d - s;
1773    set_szp_flags_32(res);
1774
1775    /* calculate the borrow chain.  See note at top */
1776    bc = (res & (~d | s)) | (~d & s);
1777    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1778    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1779    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1780    return res;
1781}
1782
1783/****************************************************************************
1784REMARKS:
1785Implements the TEST instruction and side effects.
1786****************************************************************************/
1787void test_byte(u8 d, u8 s)
1788{
1789    u32 res;   /* all operands in native machine order */
1790
1791    res = d & s;
1792
1793    CLEAR_FLAG(F_OF);
1794    set_szp_flags_8((u8)res);
1795    /* AF == dont care */
1796    CLEAR_FLAG(F_CF);
1797}
1798
1799/****************************************************************************
1800REMARKS:
1801Implements the TEST instruction and side effects.
1802****************************************************************************/
1803void test_word(u16 d, u16 s)
1804{
1805    u32 res;   /* all operands in native machine order */
1806
1807    res = d & s;
1808
1809    CLEAR_FLAG(F_OF);
1810    set_szp_flags_16((u16)res);
1811    /* AF == dont care */
1812    CLEAR_FLAG(F_CF);
1813}
1814
1815/****************************************************************************
1816REMARKS:
1817Implements the TEST instruction and side effects.
1818****************************************************************************/
1819void test_long(u32 d, u32 s)
1820{
1821    u32 res;   /* all operands in native machine order */
1822
1823    res = d & s;
1824
1825    CLEAR_FLAG(F_OF);
1826    set_szp_flags_32(res);
1827    /* AF == dont care */
1828    CLEAR_FLAG(F_CF);
1829}
1830
1831/****************************************************************************
1832REMARKS:
1833Implements the XOR instruction and side effects.
1834****************************************************************************/
1835u8 xor_byte(u8 d, u8 s)
1836{
1837    u8 res;    /* all operands in native machine order */
1838
1839    res = d ^ s;
1840    no_carry_byte_side_eff(res);
1841    return res;
1842}
1843
1844/****************************************************************************
1845REMARKS:
1846Implements the XOR instruction and side effects.
1847****************************************************************************/
1848u16 xor_word(u16 d, u16 s)
1849{
1850    u16 res;   /* all operands in native machine order */
1851
1852    res = d ^ s;
1853    no_carry_word_side_eff(res);
1854    return res;
1855}
1856
1857/****************************************************************************
1858REMARKS:
1859Implements the XOR instruction and side effects.
1860****************************************************************************/
1861u32 xor_long(u32 d, u32 s)
1862{
1863    u32 res;   /* all operands in native machine order */
1864
1865    res = d ^ s;
1866    no_carry_long_side_eff(res);
1867    return res;
1868}
1869
1870/****************************************************************************
1871REMARKS:
1872Implements the IMUL instruction and side effects.
1873****************************************************************************/
1874void imul_byte(u8 s)
1875{
1876    s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1877
1878    M.x86.R_AX = res;
1879    if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
1880        ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
1881        CLEAR_FLAG(F_CF);
1882        CLEAR_FLAG(F_OF);
1883    } else {
1884        SET_FLAG(F_CF);
1885        SET_FLAG(F_OF);
1886    }
1887}
1888
1889/****************************************************************************
1890REMARKS:
1891Implements the IMUL instruction and side effects.
1892****************************************************************************/
1893void imul_word(u16 s)
1894{
1895    s32 res = (s16)M.x86.R_AX * (s16)s;
1896
1897    M.x86.R_AX = (u16)res;
1898    M.x86.R_DX = (u16)(res >> 16);
1899    if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
1900        ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
1901        CLEAR_FLAG(F_CF);
1902        CLEAR_FLAG(F_OF);
1903    } else {
1904        SET_FLAG(F_CF);
1905        SET_FLAG(F_OF);
1906    }
1907}
1908
1909/****************************************************************************
1910REMARKS:
1911Implements the IMUL instruction and side effects.
1912****************************************************************************/
1913void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1914{
1915#ifdef  __HAS_LONG_LONG__
1916    s64 res = (s32)d * (s32)s;
1917
1918    *res_lo = (u32)res;
1919    *res_hi = (u32)(res >> 32);
1920#else
1921    u32 d_lo,d_hi,d_sign;
1922    u32 s_lo,s_hi,s_sign;
1923    u32 rlo_lo,rlo_hi,rhi_lo;
1924
1925    if ((d_sign = d & 0x80000000) != 0)
1926        d = -d;
1927    d_lo = d & 0xFFFF;
1928    d_hi = d >> 16;
1929    if ((s_sign = s & 0x80000000) != 0)
1930        s = -s;
1931    s_lo = s & 0xFFFF;
1932    s_hi = s >> 16;
1933    rlo_lo = d_lo * s_lo;
1934    rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
1935    rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
1936    *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
1937    *res_hi = rhi_lo;
1938    if (d_sign != s_sign) {
1939        d = ~*res_lo;
1940        s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1941        *res_lo = ~*res_lo+1;
1942        *res_hi = ~*res_hi+(s >> 16);
1943        }
1944#endif
1945}
1946
1947/****************************************************************************
1948REMARKS:
1949Implements the IMUL instruction and side effects.
1950****************************************************************************/
1951void imul_long(u32 s)
1952{
1953    imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
1954    if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
1955        ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
1956        CLEAR_FLAG(F_CF);
1957        CLEAR_FLAG(F_OF);
1958    } else {
1959        SET_FLAG(F_CF);
1960        SET_FLAG(F_OF);
1961    }
1962}
1963
1964/****************************************************************************
1965REMARKS:
1966Implements the MUL instruction and side effects.
1967****************************************************************************/
1968void mul_byte(u8 s)
1969{
1970    u16 res = (u16)(M.x86.R_AL * s);
1971
1972    M.x86.R_AX = res;
1973    if (M.x86.R_AH == 0) {
1974        CLEAR_FLAG(F_CF);
1975        CLEAR_FLAG(F_OF);
1976    } else {
1977        SET_FLAG(F_CF);
1978        SET_FLAG(F_OF);
1979    }
1980}
1981
1982/****************************************************************************
1983REMARKS:
1984Implements the MUL instruction and side effects.
1985****************************************************************************/
1986void mul_word(u16 s)
1987{
1988    u32 res = M.x86.R_AX * s;
1989
1990    M.x86.R_AX = (u16)res;
1991    M.x86.R_DX = (u16)(res >> 16);
1992    if (M.x86.R_DX == 0) {
1993        CLEAR_FLAG(F_CF);
1994        CLEAR_FLAG(F_OF);
1995    } else {
1996        SET_FLAG(F_CF);
1997        SET_FLAG(F_OF);
1998    }
1999}
2000
2001/****************************************************************************
2002REMARKS:
2003Implements the MUL instruction and side effects.
2004****************************************************************************/
2005void mul_long(u32 s)
2006{
2007#ifdef  __HAS_LONG_LONG__
2008    u64 res = (u32)M.x86.R_EAX * (u32)s;
2009
2010    M.x86.R_EAX = (u32)res;
2011    M.x86.R_EDX = (u32)(res >> 32);
2012#else
2013    u32 a,a_lo,a_hi;
2014    u32 s_lo,s_hi;
2015    u32 rlo_lo,rlo_hi,rhi_lo;
2016
2017    a = M.x86.R_EAX;
2018    a_lo = a & 0xFFFF;
2019    a_hi = a >> 16;
2020    s_lo = s & 0xFFFF;
2021    s_hi = s >> 16;
2022    rlo_lo = a_lo * s_lo;
2023    rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2024    rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2025    M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2026    M.x86.R_EDX = rhi_lo;
2027#endif
2028    if (M.x86.R_EDX == 0) {
2029        CLEAR_FLAG(F_CF);
2030        CLEAR_FLAG(F_OF);
2031    } else {
2032        SET_FLAG(F_CF);
2033        SET_FLAG(F_OF);
2034    }
2035}
2036
2037/****************************************************************************
2038REMARKS:
2039Implements the IDIV instruction and side effects.
2040****************************************************************************/
2041void idiv_byte(u8 s)
2042{
2043    s32 dvd, div, mod;
2044
2045    dvd = (s16)M.x86.R_AX;
2046    if (s == 0) {
2047        x86emu_intr_raise(0);
2048        return;
2049    }
2050    div = dvd / (s8)s;
2051    mod = dvd % (s8)s;
2052    if (abs(div) > 0x7f) {
2053        x86emu_intr_raise(0);
2054        return;
2055    }
2056    M.x86.R_AL = (s8) div;
2057    M.x86.R_AH = (s8) mod;
2058}
2059
2060/****************************************************************************
2061REMARKS:
2062Implements the IDIV instruction and side effects.
2063****************************************************************************/
2064void idiv_word(u16 s)
2065{
2066    s32 dvd, div, mod;
2067
2068    dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2069    if (s == 0) {
2070        x86emu_intr_raise(0);
2071        return;
2072    }
2073    div = dvd / (s16)s;
2074    mod = dvd % (s16)s;
2075    if (abs(div) > 0x7fff) {
2076        x86emu_intr_raise(0);
2077        return;
2078    }
2079    CLEAR_FLAG(F_CF);
2080    CLEAR_FLAG(F_SF);
2081    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2082    set_parity_flag(mod);
2083
2084    M.x86.R_AX = (u16)div;
2085    M.x86.R_DX = (u16)mod;
2086}
2087
2088/****************************************************************************
2089REMARKS:
2090Implements the IDIV instruction and side effects.
2091****************************************************************************/
2092void idiv_long(u32 s)
2093{
2094#ifdef  __HAS_LONG_LONG__
2095    s64 dvd, div, mod;
2096
2097    dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2098    if (s == 0) {
2099        x86emu_intr_raise(0);
2100        return;
2101    }
2102    div = dvd / (s32)s;
2103    mod = dvd % (s32)s;
2104    if (abs(div) > 0x7fffffff) {
2105        x86emu_intr_raise(0);
2106        return;
2107    }
2108#else
2109    s32 div = 0, mod;
2110    s32 h_dvd = M.x86.R_EDX;
2111    u32 l_dvd = M.x86.R_EAX;
2112    u32 abs_s = s & 0x7FFFFFFF;
2113    u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2114    u32 h_s = abs_s >> 1;
2115    u32 l_s = abs_s << 31;
2116    int counter = 31;
2117    int carry;
2118
2119    if (s == 0) {
2120        x86emu_intr_raise(0);
2121        return;
2122    }
2123    do {
2124        div <<= 1;
2125        carry = (l_dvd >= l_s) ? 0 : 1;
2126
2127        if (abs_h_dvd < (h_s + carry)) {
2128            h_s >>= 1;
2129            l_s = abs_s << (--counter);
2130            continue;
2131        } else {
2132            abs_h_dvd -= (h_s + carry);
2133            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2134                : (l_dvd - l_s);
2135            h_s >>= 1;
2136            l_s = abs_s << (--counter);
2137            div |= 1;
2138            continue;
2139        }
2140
2141    } while (counter > -1);
2142    /* overflow */
2143    if (abs_h_dvd || (l_dvd > abs_s)) {
2144        x86emu_intr_raise(0);
2145        return;
2146    }
2147    /* sign */
2148    div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2149    mod = l_dvd;
2150
2151#endif
2152    CLEAR_FLAG(F_CF);
2153    CLEAR_FLAG(F_AF);
2154    CLEAR_FLAG(F_SF);
2155    SET_FLAG(F_ZF);
2156    set_parity_flag(mod);
2157
2158    M.x86.R_EAX = (u32)div;
2159    M.x86.R_EDX = (u32)mod;
2160}
2161
2162/****************************************************************************
2163REMARKS:
2164Implements the DIV instruction and side effects.
2165****************************************************************************/
2166void div_byte(u8 s)
2167{
2168    u32 dvd, div, mod;
2169
2170    dvd = M.x86.R_AX;
2171    if (s == 0) {
2172        x86emu_intr_raise(0);
2173        return;
2174    }
2175    div = dvd / (u8)s;
2176    mod = dvd % (u8)s;
2177    if (abs(div) > 0xff) {
2178        x86emu_intr_raise(0);
2179        return;
2180    }
2181    M.x86.R_AL = (u8)div;
2182    M.x86.R_AH = (u8)mod;
2183}
2184
2185/****************************************************************************
2186REMARKS:
2187Implements the DIV instruction and side effects.
2188****************************************************************************/
2189void div_word(u16 s)
2190{
2191    u32 dvd, div, mod;
2192
2193    dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2194    if (s == 0) {
2195        x86emu_intr_raise(0);
2196        return;
2197    }
2198    div = dvd / (u16)s;
2199    mod = dvd % (u16)s;
2200    if (abs(div) > 0xffff) {
2201        x86emu_intr_raise(0);
2202        return;
2203    }
2204    CLEAR_FLAG(F_CF);
2205    CLEAR_FLAG(F_SF);
2206    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2207    set_parity_flag(mod);
2208
2209    M.x86.R_AX = (u16)div;
2210    M.x86.R_DX = (u16)mod;
2211}
2212
2213/****************************************************************************
2214REMARKS:
2215Implements the DIV instruction and side effects.
2216****************************************************************************/
2217void div_long(u32 s)
2218{
2219#ifdef  __HAS_LONG_LONG__
2220    u64 dvd, div, mod;
2221
2222    dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2223    if (s == 0) {
2224        x86emu_intr_raise(0);
2225        return;
2226    }
2227    div = dvd / (u32)s;
2228    mod = dvd % (u32)s;
2229    if (abs(div) > 0xffffffff) {
2230        x86emu_intr_raise(0);
2231        return;
2232    }
2233#else
2234    s32 div = 0, mod;
2235    s32 h_dvd = M.x86.R_EDX;
2236    u32 l_dvd = M.x86.R_EAX;
2237
2238    u32 h_s = s;
2239    u32 l_s = 0;
2240    int counter = 32;
2241    int carry;
2242
2243    if (s == 0) {
2244        x86emu_intr_raise(0);
2245        return;
2246    }
2247    do {
2248        div <<= 1;
2249        carry = (l_dvd >= l_s) ? 0 : 1;
2250
2251        if (h_dvd < (h_s + carry)) {
2252            h_s >>= 1;
2253            l_s = s << (--counter);
2254            continue;
2255        } else {
2256            h_dvd -= (h_s + carry);
2257            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2258                : (l_dvd - l_s);
2259            h_s >>= 1;
2260            l_s = s << (--counter);
2261            div |= 1;
2262            continue;
2263        }
2264
2265    } while (counter > -1);
2266    /* overflow */
2267    if (h_dvd || (l_dvd > s)) {
2268        x86emu_intr_raise(0);
2269        return;
2270    }
2271    mod = l_dvd;
2272#endif
2273    CLEAR_FLAG(F_CF);
2274    CLEAR_FLAG(F_AF);
2275    CLEAR_FLAG(F_SF);
2276    SET_FLAG(F_ZF);
2277    set_parity_flag(mod);
2278
2279    M.x86.R_EAX = (u32)div;
2280    M.x86.R_EDX = (u32)mod;
2281}
2282
2283/****************************************************************************
2284REMARKS:
2285Implements the IN string instruction and side effects.
2286****************************************************************************/
2287
2288static void single_in(int size)
2289{
2290    if(size == 1)
2291        store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
2292    else if (size == 2)
2293        store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
2294    else
2295        store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
2296}
2297
2298void ins(int size)
2299{
2300    int inc = size;
2301
2302    if (ACCESS_FLAG(F_DF)) {
2303        inc = -size;
2304    }
2305    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2306        /* dont care whether REPE or REPNE */
2307        /* in until CX is ZERO. */
2308        u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2309                     M.x86.R_ECX : M.x86.R_CX);
2310
2311        while (count--) {
2312          single_in(size);
2313          M.x86.R_DI += inc;
2314          }
2315        M.x86.R_CX = 0;
2316        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2317            M.x86.R_ECX = 0;
2318        }
2319        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2320    } else {
2321        single_in(size);
2322        M.x86.R_DI += inc;
2323    }
2324}
2325
2326/****************************************************************************
2327REMARKS:
2328Implements the OUT string instruction and side effects.
2329****************************************************************************/
2330
2331static void single_out(int size)
2332{
2333     if(size == 1)
2334       (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2335     else if (size == 2)
2336       (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2337     else
2338       (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2339}
2340
2341void outs(int size)
2342{
2343    int inc = size;
2344
2345    if (ACCESS_FLAG(F_DF)) {
2346        inc = -size;
2347    }
2348    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2349        /* dont care whether REPE or REPNE */
2350        /* out until CX is ZERO. */
2351        u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2352                     M.x86.R_ECX : M.x86.R_CX);
2353        while (count--) {
2354          single_out(size);
2355          M.x86.R_SI += inc;
2356          }
2357        M.x86.R_CX = 0;
2358        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2359            M.x86.R_ECX = 0;
2360        }
2361        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2362    } else {
2363        single_out(size);
2364        M.x86.R_SI += inc;
2365    }
2366}
2367
2368/****************************************************************************
2369PARAMETERS:
2370addr    - Address to fetch word from
2371
2372REMARKS:
2373Fetches a word from emulator memory using an absolute address.
2374****************************************************************************/
2375u16 mem_access_word(int addr)
2376{
2377DB( if (CHECK_MEM_ACCESS())
2378      x86emu_check_mem_access(addr);)
2379    return (*sys_rdw)(addr);
2380}
2381
2382/****************************************************************************
2383REMARKS:
2384Pushes a word onto the stack.
2385
2386NOTE: Do not inline this, as (*sys_wrX) is already inline!
2387****************************************************************************/
2388void push_word(u16 w)
2389{
2390DB( if (CHECK_SP_ACCESS())
2391      x86emu_check_sp_access();)
2392    M.x86.R_SP -= 2;
2393    (*sys_wrw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2394}
2395
2396/****************************************************************************
2397REMARKS:
2398Pushes a long onto the stack.
2399
2400NOTE: Do not inline this, as (*sys_wrX) is already inline!
2401****************************************************************************/
2402void push_long(u32 w)
2403{
2404DB( if (CHECK_SP_ACCESS())
2405      x86emu_check_sp_access();)
2406    M.x86.R_SP -= 4;
2407    (*sys_wrl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2408}
2409
2410/****************************************************************************
2411REMARKS:
2412Pops a word from the stack.
2413
2414NOTE: Do not inline this, as (*sys_rdX) is already inline!
2415****************************************************************************/
2416u16 pop_word(void)
2417{
2418    u16 res;
2419
2420DB( if (CHECK_SP_ACCESS())
2421      x86emu_check_sp_access();)
2422    res = (*sys_rdw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2423    M.x86.R_SP += 2;
2424    return res;
2425}
2426
2427/****************************************************************************
2428REMARKS:
2429Pops a long from the stack.
2430
2431NOTE: Do not inline this, as (*sys_rdX) is already inline!
2432****************************************************************************/
2433u32 pop_long(void)
2434{
2435    u32 res;
2436
2437DB( if (CHECK_SP_ACCESS())
2438      x86emu_check_sp_access();)
2439    res = (*sys_rdl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2440    M.x86.R_SP += 4;
2441    return res;
2442}
2443