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