blob: e0827d7478263a784d633c0f527c109beb10ded0 [file] [log] [blame]
Jason Jina63ce952007-07-06 08:34:56 +08001/****************************************************************************
2*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003* Realmode X86 Emulator Library
Jason Jina63ce952007-07-06 08:34:56 +08004*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005* Copyright (C) 1991-2004 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
Jason Jina63ce952007-07-06 08:34:56 +08008*
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
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020017* without specific, written prior permission. The authors makes no
Jason Jina63ce952007-07-06 08:34:56 +080018* 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*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020031* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
Jason Jina63ce952007-07-06 08:34:56 +080034*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020035* Description: This file contains the code to implement the primitive
36* machine operations used by the emulation code in ops.c
Jason Jina63ce952007-07-06 08:34:56 +080037*
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*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020051* 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
Jason Jina63ce952007-07-06 08:34:56 +080060*
61* Construction of table for cout:
62*
63* ab
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020064* r \ 00 01 11 10
Jason Jina63ce952007-07-06 08:34:56 +080065* |------------------
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020066* 0 | 0 1 1 1
67* 1 | 0 0 1 0
Jason Jina63ce952007-07-06 08:34:56 +080068*
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*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020078* 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
Jason Jina63ce952007-07-06 08:34:56 +080087*
88* Construction of table for cout:
89*
90* ab
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020091* r \ 00 01 11 10
Jason Jina63ce952007-07-06 08:34:56 +080092* |------------------
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020093* 0 | 0 1 0 0
94* 1 | 1 1 1 0
Jason Jina63ce952007-07-06 08:34:56 +080095*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020096* By inspection, one gets: bc = a'b + r(a' + b)
Jason Jina63ce952007-07-06 08:34:56 +080097*
98****************************************************************************/
99
100#define PRIM_OPS_NO_REDEFINE_ASM
101#include "x86emu/x86emui.h"
102
103/*------------------------- Global Variables ------------------------------*/
104
105static u32 x86emu_parity_tab[8] =
106{
107 0x96696996,
108 0x69969669,
109 0x69969669,
110 0x96696996,
111 0x69969669,
112 0x96696996,
113 0x96696996,
114 0x69969669,
115};
116
117#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200118#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
Jason Jina63ce952007-07-06 08:34:56 +0800119/*----------------------------- Implementation ----------------------------*/
120int abs(int v)
121{
122 return (v>0)?v:-v;
123}
124
125/*----------------------------- Implementation ----------------------------*/
126
127
128/*--------- Side effects helper functions -------*/
129
130/****************************************************************************
131REMARKS:
132implements side efects for byte operations that don't overflow
133****************************************************************************/
134
135static void set_parity_flag(u32 res)
136{
137 CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
138}
139
140static void set_szp_flags_8(u8 res)
141{
142 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
143 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
144 set_parity_flag(res);
145}
146
147static void set_szp_flags_16(u16 res)
148{
149 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
150 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
151 set_parity_flag(res);
152}
153
154static void set_szp_flags_32(u32 res)
155{
156 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
157 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
158 set_parity_flag(res);
159}
160
161static void no_carry_byte_side_eff(u8 res)
162{
163 CLEAR_FLAG(F_OF);
164 CLEAR_FLAG(F_CF);
165 CLEAR_FLAG(F_AF);
166 set_szp_flags_8(res);
167}
168
169static void no_carry_word_side_eff(u16 res)
170{
171 CLEAR_FLAG(F_OF);
172 CLEAR_FLAG(F_CF);
173 CLEAR_FLAG(F_AF);
174 set_szp_flags_16(res);
175}
176
177static void no_carry_long_side_eff(u32 res)
178{
179 CLEAR_FLAG(F_OF);
180 CLEAR_FLAG(F_CF);
181 CLEAR_FLAG(F_AF);
182 set_szp_flags_32(res);
183}
184
185static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
186{
187 u32 cc;
188
189 cc = (s & d) | ((~res) & (s | d));
190 CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
191 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
192 if (set_carry) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200193 CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800194 }
195}
196
197static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
198{
199 u32 bc;
200
201 bc = (res & (~d | s)) | (~d & s);
202 CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
203 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
204 if (set_carry) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200205 CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800206 }
207}
208
209/****************************************************************************
210REMARKS:
211Implements the AAA instruction and side effects.
212****************************************************************************/
213u16 aaa_word(u16 d)
214{
215 u16 res;
216 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200217 d += 0x6;
218 d += 0x100;
219 SET_FLAG(F_AF);
220 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800221 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200222 CLEAR_FLAG(F_CF);
223 CLEAR_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800224 }
225 res = (u16)(d & 0xFF0F);
226 set_szp_flags_16(res);
227 return res;
228}
229
230/****************************************************************************
231REMARKS:
232Implements the AAA instruction and side effects.
233****************************************************************************/
234u16 aas_word(u16 d)
235{
236 u16 res;
237 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200238 d -= 0x6;
239 d -= 0x100;
240 SET_FLAG(F_AF);
241 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800242 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200243 CLEAR_FLAG(F_CF);
244 CLEAR_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800245 }
246 res = (u16)(d & 0xFF0F);
247 set_szp_flags_16(res);
248 return res;
249}
250
251/****************************************************************************
252REMARKS:
253Implements the AAD instruction and side effects.
254****************************************************************************/
255u16 aad_word(u16 d)
256{
257 u16 l;
258 u8 hb, lb;
259
260 hb = (u8)((d >> 8) & 0xff);
261 lb = (u8)((d & 0xff));
262 l = (u16)((lb + 10 * hb) & 0xFF);
263
264 no_carry_byte_side_eff(l & 0xFF);
265 return l;
266}
267
268/****************************************************************************
269REMARKS:
270Implements the AAM instruction and side effects.
271****************************************************************************/
272u16 aam_word(u8 d)
273{
274 u16 h, l;
275
276 h = (u16)(d / 10);
277 l = (u16)(d % 10);
278 l |= (u16)(h << 8);
279
280 no_carry_byte_side_eff(l & 0xFF);
281 return l;
282}
283
284/****************************************************************************
285REMARKS:
286Implements the ADC instruction and side effects.
287****************************************************************************/
288u8 adc_byte(u8 d, u8 s)
289{
290 u32 res; /* all operands in native machine order */
291
292 res = d + s;
293 if (ACCESS_FLAG(F_CF)) res++;
294
295 set_szp_flags_8(res);
296 calc_carry_chain(8,s,d,res,1);
297
298 return (u8)res;
299}
300
301/****************************************************************************
302REMARKS:
303Implements the ADC instruction and side effects.
304****************************************************************************/
305u16 adc_word(u16 d, u16 s)
306{
307 u32 res; /* all operands in native machine order */
308
309 res = d + s;
310 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200311 res++;
Jason Jina63ce952007-07-06 08:34:56 +0800312
313 set_szp_flags_16((u16)res);
314 calc_carry_chain(16,s,d,res,1);
315
316 return (u16)res;
317}
318
319/****************************************************************************
320REMARKS:
321Implements the ADC instruction and side effects.
322****************************************************************************/
323u32 adc_long(u32 d, u32 s)
324{
325 u32 lo; /* all operands in native machine order */
326 u32 hi;
327 u32 res;
328
329 lo = (d & 0xFFFF) + (s & 0xFFFF);
330 res = d + s;
331
332 if (ACCESS_FLAG(F_CF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200333 lo++;
334 res++;
Jason Jina63ce952007-07-06 08:34:56 +0800335 }
336
337 hi = (lo >> 16) + (d >> 16) + (s >> 16);
338
339 set_szp_flags_32(res);
340 calc_carry_chain(32,s,d,res,0);
341
342 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
343
344 return res;
345}
346
347/****************************************************************************
348REMARKS:
349Implements the ADD instruction and side effects.
350****************************************************************************/
351u8 add_byte(u8 d, u8 s)
352{
353 u32 res; /* all operands in native machine order */
354
355 res = d + s;
356 set_szp_flags_8((u8)res);
357 calc_carry_chain(8,s,d,res,1);
358
359 return (u8)res;
360}
361
362/****************************************************************************
363REMARKS:
364Implements the ADD instruction and side effects.
365****************************************************************************/
366u16 add_word(u16 d, u16 s)
367{
368 u32 res; /* all operands in native machine order */
369
370 res = d + s;
371 set_szp_flags_16((u16)res);
372 calc_carry_chain(16,s,d,res,1);
373
374 return (u16)res;
375}
376
377/****************************************************************************
378REMARKS:
379Implements the ADD instruction and side effects.
380****************************************************************************/
381u32 add_long(u32 d, u32 s)
382{
383 u32 res;
384
385 res = d + s;
386 set_szp_flags_32(res);
387 calc_carry_chain(32,s,d,res,0);
388
389 CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
390
391 return res;
392}
393
394/****************************************************************************
395REMARKS:
396Implements the AND instruction and side effects.
397****************************************************************************/
398u8 and_byte(u8 d, u8 s)
399{
400 u8 res; /* all operands in native machine order */
401
402 res = d & s;
403
404 no_carry_byte_side_eff(res);
405 return res;
406}
407
408/****************************************************************************
409REMARKS:
410Implements the AND instruction and side effects.
411****************************************************************************/
412u16 and_word(u16 d, u16 s)
413{
414 u16 res; /* all operands in native machine order */
415
416 res = d & s;
417
418 no_carry_word_side_eff(res);
419 return res;
420}
421
422/****************************************************************************
423REMARKS:
424Implements the AND instruction and side effects.
425****************************************************************************/
426u32 and_long(u32 d, u32 s)
427{
428 u32 res; /* all operands in native machine order */
429
430 res = d & s;
431 no_carry_long_side_eff(res);
432 return res;
433}
434
435/****************************************************************************
436REMARKS:
437Implements the CMP instruction and side effects.
438****************************************************************************/
439u8 cmp_byte(u8 d, u8 s)
440{
441 u32 res; /* all operands in native machine order */
442
443 res = d - s;
444 set_szp_flags_8((u8)res);
445 calc_borrow_chain(8, d, s, res, 1);
446
447 return d;
448}
449
450/****************************************************************************
451REMARKS:
452Implements the CMP instruction and side effects.
453****************************************************************************/
454u16 cmp_word(u16 d, u16 s)
455{
456 u32 res; /* all operands in native machine order */
457
458 res = d - s;
459 set_szp_flags_16((u16)res);
460 calc_borrow_chain(16, d, s, res, 1);
461
462 return d;
463}
464
465/****************************************************************************
466REMARKS:
467Implements the CMP instruction and side effects.
468****************************************************************************/
469u32 cmp_long(u32 d, u32 s)
470{
471 u32 res; /* all operands in native machine order */
472
473 res = d - s;
474 set_szp_flags_32(res);
475 calc_borrow_chain(32, d, s, res, 1);
476
477 return d;
478}
479
480/****************************************************************************
481REMARKS:
482Implements the DAA instruction and side effects.
483****************************************************************************/
484u8 daa_byte(u8 d)
485{
486 u32 res = d;
487 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200488 res += 6;
489 SET_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800490 }
491 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200492 res += 0x60;
493 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800494 }
495 set_szp_flags_8((u8)res);
496 return (u8)res;
497}
498
499/****************************************************************************
500REMARKS:
501Implements the DAS instruction and side effects.
502****************************************************************************/
503u8 das_byte(u8 d)
504{
505 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200506 d -= 6;
507 SET_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800508 }
509 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200510 d -= 0x60;
511 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800512 }
513 set_szp_flags_8(d);
514 return d;
515}
516
517/****************************************************************************
518REMARKS:
519Implements the DEC instruction and side effects.
520****************************************************************************/
521u8 dec_byte(u8 d)
522{
523 u32 res; /* all operands in native machine order */
524
525 res = d - 1;
526 set_szp_flags_8((u8)res);
527 calc_borrow_chain(8, d, 1, res, 0);
528
529 return (u8)res;
530}
531
532/****************************************************************************
533REMARKS:
534Implements the DEC instruction and side effects.
535****************************************************************************/
536u16 dec_word(u16 d)
537{
538 u32 res; /* all operands in native machine order */
539
540 res = d - 1;
541 set_szp_flags_16((u16)res);
542 calc_borrow_chain(16, d, 1, res, 0);
543
544 return (u16)res;
545}
546
547/****************************************************************************
548REMARKS:
549Implements the DEC instruction and side effects.
550****************************************************************************/
551u32 dec_long(u32 d)
552{
553 u32 res; /* all operands in native machine order */
554
555 res = d - 1;
556
557 set_szp_flags_32(res);
558 calc_borrow_chain(32, d, 1, res, 0);
559
560 return res;
561}
562
563/****************************************************************************
564REMARKS:
565Implements the INC instruction and side effects.
566****************************************************************************/
567u8 inc_byte(u8 d)
568{
569 u32 res; /* all operands in native machine order */
570
571 res = d + 1;
572 set_szp_flags_8((u8)res);
573 calc_carry_chain(8, d, 1, res, 0);
574
575 return (u8)res;
576}
577
578/****************************************************************************
579REMARKS:
580Implements the INC instruction and side effects.
581****************************************************************************/
582u16 inc_word(u16 d)
583{
584 u32 res; /* all operands in native machine order */
585
586 res = d + 1;
587 set_szp_flags_16((u16)res);
588 calc_carry_chain(16, d, 1, res, 0);
589
590 return (u16)res;
591}
592
593/****************************************************************************
594REMARKS:
595Implements the INC instruction and side effects.
596****************************************************************************/
597u32 inc_long(u32 d)
598{
599 u32 res; /* all operands in native machine order */
600
601 res = d + 1;
602 set_szp_flags_32(res);
603 calc_carry_chain(32, d, 1, res, 0);
604
605 return res;
606}
607
608/****************************************************************************
609REMARKS:
610Implements the OR instruction and side effects.
611****************************************************************************/
612u8 or_byte(u8 d, u8 s)
613{
614 u8 res; /* all operands in native machine order */
615
616 res = d | s;
617 no_carry_byte_side_eff(res);
618
619 return res;
620}
621
622/****************************************************************************
623REMARKS:
624Implements the OR instruction and side effects.
625****************************************************************************/
626u16 or_word(u16 d, u16 s)
627{
628 u16 res; /* all operands in native machine order */
629
630 res = d | s;
631 no_carry_word_side_eff(res);
632 return res;
633}
634
635/****************************************************************************
636REMARKS:
637Implements the OR instruction and side effects.
638****************************************************************************/
639u32 or_long(u32 d, u32 s)
640{
641 u32 res; /* all operands in native machine order */
642
643 res = d | s;
644 no_carry_long_side_eff(res);
645 return res;
646}
647
648/****************************************************************************
649REMARKS:
650Implements the OR instruction and side effects.
651****************************************************************************/
652u8 neg_byte(u8 s)
653{
654 u8 res;
655
656 CONDITIONAL_SET_FLAG(s != 0, F_CF);
657 res = (u8)-s;
658 set_szp_flags_8(res);
659 calc_borrow_chain(8, 0, s, res, 0);
660
661 return res;
662}
663
664/****************************************************************************
665REMARKS:
666Implements the OR instruction and side effects.
667****************************************************************************/
668u16 neg_word(u16 s)
669{
670 u16 res;
671
672 CONDITIONAL_SET_FLAG(s != 0, F_CF);
673 res = (u16)-s;
674 set_szp_flags_16((u16)res);
675 calc_borrow_chain(16, 0, s, res, 0);
676
677 return res;
678}
679
680/****************************************************************************
681REMARKS:
682Implements the OR instruction and side effects.
683****************************************************************************/
684u32 neg_long(u32 s)
685{
686 u32 res;
687
688 CONDITIONAL_SET_FLAG(s != 0, F_CF);
689 res = (u32)-s;
690 set_szp_flags_32(res);
691 calc_borrow_chain(32, 0, s, res, 0);
692
693 return res;
694}
695
696/****************************************************************************
697REMARKS:
698Implements the NOT instruction and side effects.
699****************************************************************************/
700u8 not_byte(u8 s)
701{
702 return ~s;
703}
704
705/****************************************************************************
706REMARKS:
707Implements the NOT instruction and side effects.
708****************************************************************************/
709u16 not_word(u16 s)
710{
711 return ~s;
712}
713
714/****************************************************************************
715REMARKS:
716Implements the NOT instruction and side effects.
717****************************************************************************/
718u32 not_long(u32 s)
719{
720 return ~s;
721}
722
723/****************************************************************************
724REMARKS:
725Implements the RCL instruction and side effects.
726****************************************************************************/
727u8 rcl_byte(u8 d, u8 s)
728{
729 unsigned int res, cnt, mask, cf;
730
731 /* s is the rotate distance. It varies from 0 - 8. */
732 /* have
733
734 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
735
736 want to rotate through the carry by "s" bits. We could
737 loop, but that's inefficient. So the width is 9,
738 and we split into three parts:
739
740 The new carry flag (was B_n)
741 the stuff in B_n-1 .. B_0
742 the stuff in B_7 .. B_n+1
743
744 The new rotate is done mod 9, and given this,
745 for a rotation of n bits (mod 9) the new carry flag is
746 then located n bits from the MSB. The low part is
747 then shifted up cnt bits, and the high part is or'd
748 in. Using CAPS for new values, and lowercase for the
749 original values, this can be expressed as:
750
751 IF n > 0
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200752 1) CF <- b_(8-n)
Jason Jina63ce952007-07-06 08:34:56 +0800753 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
754 3) B_(n-1) <- cf
755 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
756 */
757 res = d;
758 if ((cnt = s % 9) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200759 /* extract the new CARRY FLAG. */
760 /* CF <- b_(8-n) */
761 cf = (d >> (8 - cnt)) & 0x1;
Jason Jina63ce952007-07-06 08:34:56 +0800762
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200763 /* get the low stuff which rotated
764 into the range B_7 .. B_cnt */
765 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
766 /* note that the right hand side done by the mask */
767 res = (d << cnt) & 0xff;
Jason Jina63ce952007-07-06 08:34:56 +0800768
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200769 /* now the high stuff which rotated around
770 into the positions B_cnt-2 .. B_0 */
771 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
772 /* shift it downward, 7-(n-2) = 9-n positions.
773 and mask off the result before or'ing in.
774 */
775 mask = (1 << (cnt - 1)) - 1;
776 res |= (d >> (9 - cnt)) & mask;
Jason Jina63ce952007-07-06 08:34:56 +0800777
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200778 /* if the carry flag was set, or it in. */
779 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
780 /* B_(n-1) <- cf */
781 res |= 1 << (cnt - 1);
782 }
783 /* set the new carry flag, based on the variable "cf" */
784 CONDITIONAL_SET_FLAG(cf, F_CF);
785 /* OVERFLOW is set *IFF* cnt==1, then it is the
786 xor of CF and the most significant bit. Blecck. */
787 /* parenthesized this expression since it appears to
788 be causing OF to be misset */
789 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
790 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +0800791
792 }
793 return (u8)res;
794}
795
796/****************************************************************************
797REMARKS:
798Implements the RCL instruction and side effects.
799****************************************************************************/
800u16 rcl_word(u16 d, u8 s)
801{
802 unsigned int res, cnt, mask, cf;
803
804 res = d;
805 if ((cnt = s % 17) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200806 cf = (d >> (16 - cnt)) & 0x1;
807 res = (d << cnt) & 0xffff;
808 mask = (1 << (cnt - 1)) - 1;
809 res |= (d >> (17 - cnt)) & mask;
810 if (ACCESS_FLAG(F_CF)) {
811 res |= 1 << (cnt - 1);
812 }
813 CONDITIONAL_SET_FLAG(cf, F_CF);
814 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
815 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +0800816 }
817 return (u16)res;
818}
819
820/****************************************************************************
821REMARKS:
822Implements the RCL instruction and side effects.
823****************************************************************************/
824u32 rcl_long(u32 d, u8 s)
825{
826 u32 res, cnt, mask, cf;
827
828 res = d;
829 if ((cnt = s % 33) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200830 cf = (d >> (32 - cnt)) & 0x1;
831 res = (d << cnt) & 0xffffffff;
832 mask = (1 << (cnt - 1)) - 1;
833 res |= (d >> (33 - cnt)) & mask;
834 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
835 res |= 1 << (cnt - 1);
836 }
837 CONDITIONAL_SET_FLAG(cf, F_CF);
838 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
839 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +0800840 }
841 return res;
842}
843
844/****************************************************************************
845REMARKS:
846Implements the RCR instruction and side effects.
847****************************************************************************/
848u8 rcr_byte(u8 d, u8 s)
849{
850 u32 res, cnt;
851 u32 mask, cf, ocf = 0;
852
853 /* rotate right through carry */
854 /*
855 s is the rotate distance. It varies from 0 - 8.
856 d is the byte object rotated.
857
858 have
859
860 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
861
862 The new rotate is done mod 9, and given this,
863 for a rotation of n bits (mod 9) the new carry flag is
864 then located n bits from the LSB. The low part is
865 then shifted up cnt bits, and the high part is or'd
866 in. Using CAPS for new values, and lowercase for the
867 original values, this can be expressed as:
868
869 IF n > 0
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200870 1) CF <- b_(n-1)
871 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
Jason Jina63ce952007-07-06 08:34:56 +0800872 3) B_(8-n) <- cf
873 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
874 */
875 res = d;
876 if ((cnt = s % 9) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200877 /* extract the new CARRY FLAG. */
878 /* CF <- b_(n-1) */
879 if (cnt == 1) {
880 cf = d & 0x1;
881 /* note hackery here. Access_flag(..) evaluates to either
882 0 if flag not set
883 non-zero if flag is set.
884 doing access_flag(..) != 0 casts that into either
885 0..1 in any representation of the flags register
886 (i.e. packed bit array or unpacked.)
887 */
888 ocf = ACCESS_FLAG(F_CF) != 0;
889 } else
890 cf = (d >> (cnt - 1)) & 0x1;
Jason Jina63ce952007-07-06 08:34:56 +0800891
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200892 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
893 /* note that the right hand side done by the mask
894 This is effectively done by shifting the
895 object to the right. The result must be masked,
896 in case the object came in and was treated
897 as a negative number. Needed??? */
Jason Jina63ce952007-07-06 08:34:56 +0800898
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200899 mask = (1 << (8 - cnt)) - 1;
900 res = (d >> cnt) & mask;
Jason Jina63ce952007-07-06 08:34:56 +0800901
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200902 /* now the high stuff which rotated around
903 into the positions B_cnt-2 .. B_0 */
904 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
905 /* shift it downward, 7-(n-2) = 9-n positions.
906 and mask off the result before or'ing in.
907 */
908 res |= (d << (9 - cnt));
Jason Jina63ce952007-07-06 08:34:56 +0800909
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200910 /* if the carry flag was set, or it in. */
911 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
912 /* B_(8-n) <- cf */
913 res |= 1 << (8 - cnt);
914 }
915 /* set the new carry flag, based on the variable "cf" */
916 CONDITIONAL_SET_FLAG(cf, F_CF);
917 /* OVERFLOW is set *IFF* cnt==1, then it is the
918 xor of CF and the most significant bit. Blecck. */
919 /* parenthesized... */
920 if (cnt == 1) {
921 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
922 F_OF);
923 }
Jason Jina63ce952007-07-06 08:34:56 +0800924 }
925 return (u8)res;
926}
927
928/****************************************************************************
929REMARKS:
930Implements the RCR instruction and side effects.
931****************************************************************************/
932u16 rcr_word(u16 d, u8 s)
933{
934 u32 res, cnt;
935 u32 mask, cf, ocf = 0;
936
937 /* rotate right through carry */
938 res = d;
939 if ((cnt = s % 17) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200940 if (cnt == 1) {
941 cf = d & 0x1;
942 ocf = ACCESS_FLAG(F_CF) != 0;
943 } else
944 cf = (d >> (cnt - 1)) & 0x1;
945 mask = (1 << (16 - cnt)) - 1;
946 res = (d >> cnt) & mask;
947 res |= (d << (17 - cnt));
948 if (ACCESS_FLAG(F_CF)) {
949 res |= 1 << (16 - cnt);
950 }
951 CONDITIONAL_SET_FLAG(cf, F_CF);
952 if (cnt == 1) {
953 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
954 F_OF);
955 }
Jason Jina63ce952007-07-06 08:34:56 +0800956 }
957 return (u16)res;
958}
959
960/****************************************************************************
961REMARKS:
962Implements the RCR instruction and side effects.
963****************************************************************************/
964u32 rcr_long(u32 d, u8 s)
965{
966 u32 res, cnt;
967 u32 mask, cf, ocf = 0;
968
969 /* rotate right through carry */
970 res = d;
971 if ((cnt = s % 33) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200972 if (cnt == 1) {
973 cf = d & 0x1;
974 ocf = ACCESS_FLAG(F_CF) != 0;
975 } else
976 cf = (d >> (cnt - 1)) & 0x1;
977 mask = (1 << (32 - cnt)) - 1;
978 res = (d >> cnt) & mask;
979 if (cnt != 1)
980 res |= (d << (33 - cnt));
981 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
982 res |= 1 << (32 - cnt);
983 }
984 CONDITIONAL_SET_FLAG(cf, F_CF);
985 if (cnt == 1) {
986 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
987 F_OF);
988 }
Jason Jina63ce952007-07-06 08:34:56 +0800989 }
990 return res;
991}
992
993/****************************************************************************
994REMARKS:
995Implements the ROL instruction and side effects.
996****************************************************************************/
997u8 rol_byte(u8 d, u8 s)
998{
999 unsigned int res, cnt, mask;
1000
1001 /* rotate left */
1002 /*
1003 s is the rotate distance. It varies from 0 - 8.
1004 d is the byte object rotated.
1005
1006 have
1007
1008 CF B_7 ... B_0
1009
1010 The new rotate is done mod 8.
1011 Much simpler than the "rcl" or "rcr" operations.
1012
1013 IF n > 0
1014 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1015 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1016 */
1017 res = d;
1018 if ((cnt = s % 8) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001019 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1020 res = (d << cnt);
Jason Jina63ce952007-07-06 08:34:56 +08001021
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001022 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1023 mask = (1 << cnt) - 1;
1024 res |= (d >> (8 - cnt)) & mask;
Jason Jina63ce952007-07-06 08:34:56 +08001025
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001026 /* set the new carry flag, Note that it is the low order
1027 bit of the result!!! */
1028 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1029 /* OVERFLOW is set *IFF* s==1, then it is the
1030 xor of CF and the most significant bit. Blecck. */
1031 CONDITIONAL_SET_FLAG(s == 1 &&
1032 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1033 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001034 } if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001035 /* set the new carry flag, Note that it is the low order
1036 bit of the result!!! */
1037 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001038 }
1039 return (u8)res;
1040}
1041
1042/****************************************************************************
1043REMARKS:
1044Implements the ROL instruction and side effects.
1045****************************************************************************/
1046u16 rol_word(u16 d, u8 s)
1047{
1048 unsigned int res, cnt, mask;
1049
1050 res = d;
1051 if ((cnt = s % 16) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001052 res = (d << cnt);
1053 mask = (1 << cnt) - 1;
1054 res |= (d >> (16 - cnt)) & mask;
1055 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1056 CONDITIONAL_SET_FLAG(s == 1 &&
1057 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1058 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001059 } if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001060 /* set the new carry flag, Note that it is the low order
1061 bit of the result!!! */
1062 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001063 }
1064 return (u16)res;
1065}
1066
1067/****************************************************************************
1068REMARKS:
1069Implements the ROL instruction and side effects.
1070****************************************************************************/
1071u32 rol_long(u32 d, u8 s)
1072{
1073 u32 res, cnt, mask;
1074
1075 res = d;
1076 if ((cnt = s % 32) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001077 res = (d << cnt);
1078 mask = (1 << cnt) - 1;
1079 res |= (d >> (32 - cnt)) & mask;
1080 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1081 CONDITIONAL_SET_FLAG(s == 1 &&
1082 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1083 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001084 } if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001085 /* set the new carry flag, Note that it is the low order
1086 bit of the result!!! */
1087 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001088 }
1089 return res;
1090}
1091
1092/****************************************************************************
1093REMARKS:
1094Implements the ROR instruction and side effects.
1095****************************************************************************/
1096u8 ror_byte(u8 d, u8 s)
1097{
1098 unsigned int res, cnt, mask;
1099
1100 /* rotate right */
1101 /*
1102 s is the rotate distance. It varies from 0 - 8.
1103 d is the byte object rotated.
1104
1105 have
1106
1107 B_7 ... B_0
1108
1109 The rotate is done mod 8.
1110
1111 IF n > 0
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001112 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
Jason Jina63ce952007-07-06 08:34:56 +08001113 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1114 */
1115 res = d;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001116 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
1117 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1118 res = (d << (8 - cnt));
Jason Jina63ce952007-07-06 08:34:56 +08001119
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001120 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1121 mask = (1 << (8 - cnt)) - 1;
1122 res |= (d >> (cnt)) & mask;
Jason Jina63ce952007-07-06 08:34:56 +08001123
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001124 /* set the new carry flag, Note that it is the low order
1125 bit of the result!!! */
1126 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1127 /* OVERFLOW is set *IFF* s==1, then it is the
1128 xor of the two most significant bits. Blecck. */
1129 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001130 } else if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001131 /* set the new carry flag, Note that it is the low order
1132 bit of the result!!! */
1133 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001134 }
1135 return (u8)res;
1136}
1137
1138/****************************************************************************
1139REMARKS:
1140Implements the ROR instruction and side effects.
1141****************************************************************************/
1142u16 ror_word(u16 d, u8 s)
1143{
1144 unsigned int res, cnt, mask;
1145
1146 res = d;
1147 if ((cnt = s % 16) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001148 res = (d << (16 - cnt));
1149 mask = (1 << (16 - cnt)) - 1;
1150 res |= (d >> (cnt)) & mask;
1151 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1152 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001153 } else if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001154 /* set the new carry flag, Note that it is the low order
1155 bit of the result!!! */
1156 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001157 }
1158 return (u16)res;
1159}
1160
1161/****************************************************************************
1162REMARKS:
1163Implements the ROR instruction and side effects.
1164****************************************************************************/
1165u32 ror_long(u32 d, u8 s)
1166{
1167 u32 res, cnt, mask;
1168
1169 res = d;
1170 if ((cnt = s % 32) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001171 res = (d << (32 - cnt));
1172 mask = (1 << (32 - cnt)) - 1;
1173 res |= (d >> (cnt)) & mask;
1174 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1175 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001176 } else if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001177 /* set the new carry flag, Note that it is the low order
1178 bit of the result!!! */
1179 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001180 }
1181 return res;
1182}
1183
1184/****************************************************************************
1185REMARKS:
1186Implements the SHL instruction and side effects.
1187****************************************************************************/
1188u8 shl_byte(u8 d, u8 s)
1189{
1190 unsigned int cnt, res, cf;
1191
1192 if (s < 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001193 cnt = s % 8;
Jason Jina63ce952007-07-06 08:34:56 +08001194
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001195 /* last bit shifted out goes into carry flag */
1196 if (cnt > 0) {
1197 res = d << cnt;
1198 cf = d & (1 << (8 - cnt));
1199 CONDITIONAL_SET_FLAG(cf, F_CF);
1200 set_szp_flags_8((u8)res);
1201 } else {
1202 res = (u8) d;
1203 }
Jason Jina63ce952007-07-06 08:34:56 +08001204
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001205 if (cnt == 1) {
1206 /* Needs simplification. */
1207 CONDITIONAL_SET_FLAG(
1208 (((res & 0x80) == 0x80) ^
1209 (ACCESS_FLAG(F_CF) != 0)),
1210 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1211 F_OF);
1212 } else {
1213 CLEAR_FLAG(F_OF);
1214 }
Jason Jina63ce952007-07-06 08:34:56 +08001215 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001216 res = 0;
1217 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1218 CLEAR_FLAG(F_OF);
1219 CLEAR_FLAG(F_SF);
1220 SET_FLAG(F_PF);
1221 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001222 }
1223 return (u8)res;
1224}
1225
1226/****************************************************************************
1227REMARKS:
1228Implements the SHL instruction and side effects.
1229****************************************************************************/
1230u16 shl_word(u16 d, u8 s)
1231{
1232 unsigned int cnt, res, cf;
1233
1234 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001235 cnt = s % 16;
1236 if (cnt > 0) {
1237 res = d << cnt;
1238 cf = d & (1 << (16 - cnt));
1239 CONDITIONAL_SET_FLAG(cf, F_CF);
1240 set_szp_flags_16((u16)res);
1241 } else {
1242 res = (u16) d;
1243 }
Jason Jina63ce952007-07-06 08:34:56 +08001244
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001245 if (cnt == 1) {
1246 CONDITIONAL_SET_FLAG(
1247 (((res & 0x8000) == 0x8000) ^
1248 (ACCESS_FLAG(F_CF) != 0)),
1249 F_OF);
1250 } else {
1251 CLEAR_FLAG(F_OF);
1252 }
Jason Jina63ce952007-07-06 08:34:56 +08001253 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001254 res = 0;
1255 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1256 CLEAR_FLAG(F_OF);
1257 CLEAR_FLAG(F_SF);
1258 SET_FLAG(F_PF);
1259 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001260 }
1261 return (u16)res;
1262}
1263
1264/****************************************************************************
1265REMARKS:
1266Implements the SHL instruction and side effects.
1267****************************************************************************/
1268u32 shl_long(u32 d, u8 s)
1269{
1270 unsigned int cnt, res, cf;
1271
1272 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001273 cnt = s % 32;
1274 if (cnt > 0) {
1275 res = d << cnt;
1276 cf = d & (1 << (32 - cnt));
1277 CONDITIONAL_SET_FLAG(cf, F_CF);
1278 set_szp_flags_32((u32)res);
1279 } else {
1280 res = d;
1281 }
1282 if (cnt == 1) {
1283 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1284 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1285 } else {
1286 CLEAR_FLAG(F_OF);
1287 }
Jason Jina63ce952007-07-06 08:34:56 +08001288 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001289 res = 0;
1290 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1291 CLEAR_FLAG(F_OF);
1292 CLEAR_FLAG(F_SF);
1293 SET_FLAG(F_PF);
1294 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001295 }
1296 return res;
1297}
1298
1299/****************************************************************************
1300REMARKS:
1301Implements the SHR instruction and side effects.
1302****************************************************************************/
1303u8 shr_byte(u8 d, u8 s)
1304{
1305 unsigned int cnt, res, cf;
1306
1307 if (s < 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001308 cnt = s % 8;
1309 if (cnt > 0) {
1310 cf = d & (1 << (cnt - 1));
1311 res = d >> cnt;
1312 CONDITIONAL_SET_FLAG(cf, F_CF);
1313 set_szp_flags_8((u8)res);
1314 } else {
1315 res = (u8) d;
1316 }
Jason Jina63ce952007-07-06 08:34:56 +08001317
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001318 if (cnt == 1) {
1319 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1320 } else {
1321 CLEAR_FLAG(F_OF);
1322 }
Jason Jina63ce952007-07-06 08:34:56 +08001323 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001324 res = 0;
1325 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1326 CLEAR_FLAG(F_OF);
1327 CLEAR_FLAG(F_SF);
1328 SET_FLAG(F_PF);
1329 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001330 }
1331 return (u8)res;
1332}
1333
1334/****************************************************************************
1335REMARKS:
1336Implements the SHR instruction and side effects.
1337****************************************************************************/
1338u16 shr_word(u16 d, u8 s)
1339{
1340 unsigned int cnt, res, cf;
1341
1342 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001343 cnt = s % 16;
1344 if (cnt > 0) {
1345 cf = d & (1 << (cnt - 1));
1346 res = d >> cnt;
1347 CONDITIONAL_SET_FLAG(cf, F_CF);
1348 set_szp_flags_16((u16)res);
1349 } else {
1350 res = d;
1351 }
Jason Jina63ce952007-07-06 08:34:56 +08001352
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001353 if (cnt == 1) {
1354 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1355 } else {
1356 CLEAR_FLAG(F_OF);
1357 }
Jason Jina63ce952007-07-06 08:34:56 +08001358 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001359 res = 0;
1360 CLEAR_FLAG(F_CF);
1361 CLEAR_FLAG(F_OF);
1362 SET_FLAG(F_ZF);
1363 CLEAR_FLAG(F_SF);
1364 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001365 }
1366 return (u16)res;
1367}
1368
1369/****************************************************************************
1370REMARKS:
1371Implements the SHR instruction and side effects.
1372****************************************************************************/
1373u32 shr_long(u32 d, u8 s)
1374{
1375 unsigned int cnt, res, cf;
1376
1377 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001378 cnt = s % 32;
1379 if (cnt > 0) {
1380 cf = d & (1 << (cnt - 1));
1381 res = d >> cnt;
1382 CONDITIONAL_SET_FLAG(cf, F_CF);
1383 set_szp_flags_32((u32)res);
1384 } else {
1385 res = d;
1386 }
1387 if (cnt == 1) {
1388 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1389 } else {
1390 CLEAR_FLAG(F_OF);
1391 }
Jason Jina63ce952007-07-06 08:34:56 +08001392 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001393 res = 0;
1394 CLEAR_FLAG(F_CF);
1395 CLEAR_FLAG(F_OF);
1396 SET_FLAG(F_ZF);
1397 CLEAR_FLAG(F_SF);
1398 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001399 }
1400 return res;
1401}
1402
1403/****************************************************************************
1404REMARKS:
1405Implements the SAR instruction and side effects.
1406****************************************************************************/
1407u8 sar_byte(u8 d, u8 s)
1408{
1409 unsigned int cnt, res, cf, mask, sf;
1410
1411 res = d;
1412 sf = d & 0x80;
1413 cnt = s % 8;
1414 if (cnt > 0 && cnt < 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001415 mask = (1 << (8 - cnt)) - 1;
1416 cf = d & (1 << (cnt - 1));
1417 res = (d >> cnt) & mask;
1418 CONDITIONAL_SET_FLAG(cf, F_CF);
1419 if (sf) {
1420 res |= ~mask;
1421 }
1422 set_szp_flags_8((u8)res);
Jason Jina63ce952007-07-06 08:34:56 +08001423 } else if (cnt >= 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001424 if (sf) {
1425 res = 0xff;
1426 SET_FLAG(F_CF);
1427 CLEAR_FLAG(F_ZF);
1428 SET_FLAG(F_SF);
1429 SET_FLAG(F_PF);
1430 } else {
1431 res = 0;
1432 CLEAR_FLAG(F_CF);
1433 SET_FLAG(F_ZF);
1434 CLEAR_FLAG(F_SF);
1435 CLEAR_FLAG(F_PF);
1436 }
Jason Jina63ce952007-07-06 08:34:56 +08001437 }
1438 return (u8)res;
1439}
1440
1441/****************************************************************************
1442REMARKS:
1443Implements the SAR instruction and side effects.
1444****************************************************************************/
1445u16 sar_word(u16 d, u8 s)
1446{
1447 unsigned int cnt, res, cf, mask, sf;
1448
1449 sf = d & 0x8000;
1450 cnt = s % 16;
1451 res = d;
1452 if (cnt > 0 && cnt < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001453 mask = (1 << (16 - cnt)) - 1;
1454 cf = d & (1 << (cnt - 1));
1455 res = (d >> cnt) & mask;
1456 CONDITIONAL_SET_FLAG(cf, F_CF);
1457 if (sf) {
1458 res |= ~mask;
1459 }
1460 set_szp_flags_16((u16)res);
Jason Jina63ce952007-07-06 08:34:56 +08001461 } else if (cnt >= 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001462 if (sf) {
1463 res = 0xffff;
1464 SET_FLAG(F_CF);
1465 CLEAR_FLAG(F_ZF);
1466 SET_FLAG(F_SF);
1467 SET_FLAG(F_PF);
1468 } else {
1469 res = 0;
1470 CLEAR_FLAG(F_CF);
1471 SET_FLAG(F_ZF);
1472 CLEAR_FLAG(F_SF);
1473 CLEAR_FLAG(F_PF);
1474 }
Jason Jina63ce952007-07-06 08:34:56 +08001475 }
1476 return (u16)res;
1477}
1478
1479/****************************************************************************
1480REMARKS:
1481Implements the SAR instruction and side effects.
1482****************************************************************************/
1483u32 sar_long(u32 d, u8 s)
1484{
1485 u32 cnt, res, cf, mask, sf;
1486
1487 sf = d & 0x80000000;
1488 cnt = s % 32;
1489 res = d;
1490 if (cnt > 0 && cnt < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001491 mask = (1 << (32 - cnt)) - 1;
1492 cf = d & (1 << (cnt - 1));
1493 res = (d >> cnt) & mask;
1494 CONDITIONAL_SET_FLAG(cf, F_CF);
1495 if (sf) {
1496 res |= ~mask;
1497 }
1498 set_szp_flags_32(res);
Jason Jina63ce952007-07-06 08:34:56 +08001499 } else if (cnt >= 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001500 if (sf) {
1501 res = 0xffffffff;
1502 SET_FLAG(F_CF);
1503 CLEAR_FLAG(F_ZF);
1504 SET_FLAG(F_SF);
1505 SET_FLAG(F_PF);
1506 } else {
1507 res = 0;
1508 CLEAR_FLAG(F_CF);
1509 SET_FLAG(F_ZF);
1510 CLEAR_FLAG(F_SF);
1511 CLEAR_FLAG(F_PF);
1512 }
Jason Jina63ce952007-07-06 08:34:56 +08001513 }
1514 return res;
1515}
1516
1517/****************************************************************************
1518REMARKS:
1519Implements the SHLD instruction and side effects.
1520****************************************************************************/
1521u16 shld_word (u16 d, u16 fill, u8 s)
1522{
1523 unsigned int cnt, res, cf;
1524
1525 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001526 cnt = s % 16;
1527 if (cnt > 0) {
1528 res = (d << cnt) | (fill >> (16-cnt));
1529 cf = d & (1 << (16 - cnt));
1530 CONDITIONAL_SET_FLAG(cf, F_CF);
1531 set_szp_flags_16((u16)res);
1532 } else {
1533 res = d;
1534 }
1535 if (cnt == 1) {
1536 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1537 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1538 } else {
1539 CLEAR_FLAG(F_OF);
1540 }
Jason Jina63ce952007-07-06 08:34:56 +08001541 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001542 res = 0;
1543 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1544 CLEAR_FLAG(F_OF);
1545 CLEAR_FLAG(F_SF);
1546 SET_FLAG(F_PF);
1547 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001548 }
1549 return (u16)res;
1550}
1551
1552/****************************************************************************
1553REMARKS:
1554Implements the SHLD instruction and side effects.
1555****************************************************************************/
1556u32 shld_long (u32 d, u32 fill, u8 s)
1557{
1558 unsigned int cnt, res, cf;
1559
1560 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001561 cnt = s % 32;
1562 if (cnt > 0) {
1563 res = (d << cnt) | (fill >> (32-cnt));
1564 cf = d & (1 << (32 - cnt));
1565 CONDITIONAL_SET_FLAG(cf, F_CF);
1566 set_szp_flags_32((u32)res);
1567 } else {
1568 res = d;
1569 }
1570 if (cnt == 1) {
1571 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1572 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1573 } else {
1574 CLEAR_FLAG(F_OF);
1575 }
Jason Jina63ce952007-07-06 08:34:56 +08001576 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001577 res = 0;
1578 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1579 CLEAR_FLAG(F_OF);
1580 CLEAR_FLAG(F_SF);
1581 SET_FLAG(F_PF);
1582 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001583 }
1584 return res;
1585}
1586
1587/****************************************************************************
1588REMARKS:
1589Implements the SHRD instruction and side effects.
1590****************************************************************************/
1591u16 shrd_word (u16 d, u16 fill, u8 s)
1592{
1593 unsigned int cnt, res, cf;
1594
1595 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001596 cnt = s % 16;
1597 if (cnt > 0) {
1598 cf = d & (1 << (cnt - 1));
1599 res = (d >> cnt) | (fill << (16 - cnt));
1600 CONDITIONAL_SET_FLAG(cf, F_CF);
1601 set_szp_flags_16((u16)res);
1602 } else {
1603 res = d;
1604 }
Jason Jina63ce952007-07-06 08:34:56 +08001605
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001606 if (cnt == 1) {
1607 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1608 } else {
1609 CLEAR_FLAG(F_OF);
1610 }
Jason Jina63ce952007-07-06 08:34:56 +08001611 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001612 res = 0;
1613 CLEAR_FLAG(F_CF);
1614 CLEAR_FLAG(F_OF);
1615 SET_FLAG(F_ZF);
1616 CLEAR_FLAG(F_SF);
1617 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001618 }
1619 return (u16)res;
1620}
1621
1622/****************************************************************************
1623REMARKS:
1624Implements the SHRD instruction and side effects.
1625****************************************************************************/
1626u32 shrd_long (u32 d, u32 fill, u8 s)
1627{
1628 unsigned int cnt, res, cf;
1629
1630 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001631 cnt = s % 32;
1632 if (cnt > 0) {
1633 cf = d & (1 << (cnt - 1));
1634 res = (d >> cnt) | (fill << (32 - cnt));
1635 CONDITIONAL_SET_FLAG(cf, F_CF);
1636 set_szp_flags_32((u32)res);
1637 } else {
1638 res = d;
1639 }
1640 if (cnt == 1) {
1641 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1642 } else {
1643 CLEAR_FLAG(F_OF);
1644 }
Jason Jina63ce952007-07-06 08:34:56 +08001645 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001646 res = 0;
1647 CLEAR_FLAG(F_CF);
1648 CLEAR_FLAG(F_OF);
1649 SET_FLAG(F_ZF);
1650 CLEAR_FLAG(F_SF);
1651 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001652 }
1653 return res;
1654}
1655
1656/****************************************************************************
1657REMARKS:
1658Implements the SBB instruction and side effects.
1659****************************************************************************/
1660u8 sbb_byte(u8 d, u8 s)
1661{
1662 u32 res; /* all operands in native machine order */
1663 u32 bc;
1664
1665 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001666 res = d - s - 1;
Jason Jina63ce952007-07-06 08:34:56 +08001667 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001668 res = d - s;
Jason Jina63ce952007-07-06 08:34:56 +08001669 set_szp_flags_8((u8)res);
1670
1671 /* calculate the borrow chain. See note at top */
1672 bc = (res & (~d | s)) | (~d & s);
1673 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1674 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1675 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1676 return (u8)res;
1677}
1678
1679/****************************************************************************
1680REMARKS:
1681Implements the SBB instruction and side effects.
1682****************************************************************************/
1683u16 sbb_word(u16 d, u16 s)
1684{
1685 u32 res; /* all operands in native machine order */
1686 u32 bc;
1687
1688 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001689 res = d - s - 1;
Jason Jina63ce952007-07-06 08:34:56 +08001690 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001691 res = d - s;
Jason Jina63ce952007-07-06 08:34:56 +08001692 set_szp_flags_16((u16)res);
1693
1694 /* calculate the borrow chain. See note at top */
1695 bc = (res & (~d | s)) | (~d & s);
1696 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1697 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1698 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1699 return (u16)res;
1700}
1701
1702/****************************************************************************
1703REMARKS:
1704Implements the SBB instruction and side effects.
1705****************************************************************************/
1706u32 sbb_long(u32 d, u32 s)
1707{
1708 u32 res; /* all operands in native machine order */
1709 u32 bc;
1710
1711 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001712 res = d - s - 1;
Jason Jina63ce952007-07-06 08:34:56 +08001713 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001714 res = d - s;
Jason Jina63ce952007-07-06 08:34:56 +08001715
1716 set_szp_flags_32(res);
1717
1718 /* calculate the borrow chain. See note at top */
1719 bc = (res & (~d | s)) | (~d & s);
1720 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1721 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1722 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1723 return res;
1724}
1725
1726/****************************************************************************
1727REMARKS:
1728Implements the SUB instruction and side effects.
1729****************************************************************************/
1730u8 sub_byte(u8 d, u8 s)
1731{
1732 u32 res; /* all operands in native machine order */
1733 u32 bc;
1734
1735 res = d - s;
1736 set_szp_flags_8((u8)res);
1737
1738 /* calculate the borrow chain. See note at top */
1739 bc = (res & (~d | s)) | (~d & s);
1740 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1741 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1742 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1743 return (u8)res;
1744}
1745
1746/****************************************************************************
1747REMARKS:
1748Implements the SUB instruction and side effects.
1749****************************************************************************/
1750u16 sub_word(u16 d, u16 s)
1751{
1752 u32 res; /* all operands in native machine order */
1753 u32 bc;
1754
1755 res = d - s;
1756 set_szp_flags_16((u16)res);
1757
1758 /* calculate the borrow chain. See note at top */
1759 bc = (res & (~d | s)) | (~d & s);
1760 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1761 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1762 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1763 return (u16)res;
1764}
1765
1766/****************************************************************************
1767REMARKS:
1768Implements the SUB instruction and side effects.
1769****************************************************************************/
1770u32 sub_long(u32 d, u32 s)
1771{
1772 u32 res; /* all operands in native machine order */
1773 u32 bc;
1774
1775 res = d - s;
1776 set_szp_flags_32(res);
1777
1778 /* calculate the borrow chain. See note at top */
1779 bc = (res & (~d | s)) | (~d & s);
1780 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1781 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1782 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1783 return res;
1784}
1785
1786/****************************************************************************
1787REMARKS:
1788Implements the TEST instruction and side effects.
1789****************************************************************************/
1790void test_byte(u8 d, u8 s)
1791{
1792 u32 res; /* all operands in native machine order */
1793
1794 res = d & s;
1795
1796 CLEAR_FLAG(F_OF);
1797 set_szp_flags_8((u8)res);
1798 /* AF == dont care */
1799 CLEAR_FLAG(F_CF);
1800}
1801
1802/****************************************************************************
1803REMARKS:
1804Implements the TEST instruction and side effects.
1805****************************************************************************/
1806void test_word(u16 d, u16 s)
1807{
1808 u32 res; /* all operands in native machine order */
1809
1810 res = d & s;
1811
1812 CLEAR_FLAG(F_OF);
1813 set_szp_flags_16((u16)res);
1814 /* AF == dont care */
1815 CLEAR_FLAG(F_CF);
1816}
1817
1818/****************************************************************************
1819REMARKS:
1820Implements the TEST instruction and side effects.
1821****************************************************************************/
1822void test_long(u32 d, u32 s)
1823{
1824 u32 res; /* all operands in native machine order */
1825
1826 res = d & s;
1827
1828 CLEAR_FLAG(F_OF);
1829 set_szp_flags_32(res);
1830 /* AF == dont care */
1831 CLEAR_FLAG(F_CF);
1832}
1833
1834/****************************************************************************
1835REMARKS:
1836Implements the XOR instruction and side effects.
1837****************************************************************************/
1838u8 xor_byte(u8 d, u8 s)
1839{
1840 u8 res; /* all operands in native machine order */
1841
1842 res = d ^ s;
1843 no_carry_byte_side_eff(res);
1844 return res;
1845}
1846
1847/****************************************************************************
1848REMARKS:
1849Implements the XOR instruction and side effects.
1850****************************************************************************/
1851u16 xor_word(u16 d, u16 s)
1852{
1853 u16 res; /* all operands in native machine order */
1854
1855 res = d ^ s;
1856 no_carry_word_side_eff(res);
1857 return res;
1858}
1859
1860/****************************************************************************
1861REMARKS:
1862Implements the XOR instruction and side effects.
1863****************************************************************************/
1864u32 xor_long(u32 d, u32 s)
1865{
1866 u32 res; /* all operands in native machine order */
1867
1868 res = d ^ s;
1869 no_carry_long_side_eff(res);
1870 return res;
1871}
1872
1873/****************************************************************************
1874REMARKS:
1875Implements the IMUL instruction and side effects.
1876****************************************************************************/
1877void imul_byte(u8 s)
1878{
1879 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1880
1881 M.x86.R_AX = res;
1882 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001883 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
1884 CLEAR_FLAG(F_CF);
1885 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001886 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001887 SET_FLAG(F_CF);
1888 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001889 }
1890}
1891
1892/****************************************************************************
1893REMARKS:
1894Implements the IMUL instruction and side effects.
1895****************************************************************************/
1896void imul_word(u16 s)
1897{
1898 s32 res = (s16)M.x86.R_AX * (s16)s;
1899
1900 M.x86.R_AX = (u16)res;
1901 M.x86.R_DX = (u16)(res >> 16);
1902 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001903 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
1904 CLEAR_FLAG(F_CF);
1905 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001906 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001907 SET_FLAG(F_CF);
1908 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001909 }
1910}
1911
1912/****************************************************************************
1913REMARKS:
1914Implements the IMUL instruction and side effects.
1915****************************************************************************/
1916void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1917{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001918#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08001919 s64 res = (s32)d * (s32)s;
1920
1921 *res_lo = (u32)res;
1922 *res_hi = (u32)(res >> 32);
1923#else
1924 u32 d_lo,d_hi,d_sign;
1925 u32 s_lo,s_hi,s_sign;
1926 u32 rlo_lo,rlo_hi,rhi_lo;
1927
1928 if ((d_sign = d & 0x80000000) != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001929 d = -d;
Jason Jina63ce952007-07-06 08:34:56 +08001930 d_lo = d & 0xFFFF;
1931 d_hi = d >> 16;
1932 if ((s_sign = s & 0x80000000) != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001933 s = -s;
Jason Jina63ce952007-07-06 08:34:56 +08001934 s_lo = s & 0xFFFF;
1935 s_hi = s >> 16;
1936 rlo_lo = d_lo * s_lo;
1937 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
1938 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
1939 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
1940 *res_hi = rhi_lo;
1941 if (d_sign != s_sign) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001942 d = ~*res_lo;
1943 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1944 *res_lo = ~*res_lo+1;
1945 *res_hi = ~*res_hi+(s >> 16);
1946 }
Jason Jina63ce952007-07-06 08:34:56 +08001947#endif
1948}
1949
1950/****************************************************************************
1951REMARKS:
1952Implements the IMUL instruction and side effects.
1953****************************************************************************/
1954void imul_long(u32 s)
1955{
1956 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
1957 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001958 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
1959 CLEAR_FLAG(F_CF);
1960 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001961 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001962 SET_FLAG(F_CF);
1963 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001964 }
1965}
1966
1967/****************************************************************************
1968REMARKS:
1969Implements the MUL instruction and side effects.
1970****************************************************************************/
1971void mul_byte(u8 s)
1972{
1973 u16 res = (u16)(M.x86.R_AL * s);
1974
1975 M.x86.R_AX = res;
1976 if (M.x86.R_AH == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001977 CLEAR_FLAG(F_CF);
1978 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001979 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001980 SET_FLAG(F_CF);
1981 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001982 }
1983}
1984
1985/****************************************************************************
1986REMARKS:
1987Implements the MUL instruction and side effects.
1988****************************************************************************/
1989void mul_word(u16 s)
1990{
1991 u32 res = M.x86.R_AX * s;
1992
1993 M.x86.R_AX = (u16)res;
1994 M.x86.R_DX = (u16)(res >> 16);
1995 if (M.x86.R_DX == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001996 CLEAR_FLAG(F_CF);
1997 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001998 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001999 SET_FLAG(F_CF);
2000 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002001 }
2002}
2003
2004/****************************************************************************
2005REMARKS:
2006Implements the MUL instruction and side effects.
2007****************************************************************************/
2008void mul_long(u32 s)
2009{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002010#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08002011 u64 res = (u32)M.x86.R_EAX * (u32)s;
2012
2013 M.x86.R_EAX = (u32)res;
2014 M.x86.R_EDX = (u32)(res >> 32);
2015#else
2016 u32 a,a_lo,a_hi;
2017 u32 s_lo,s_hi;
2018 u32 rlo_lo,rlo_hi,rhi_lo;
2019
2020 a = M.x86.R_EAX;
2021 a_lo = a & 0xFFFF;
2022 a_hi = a >> 16;
2023 s_lo = s & 0xFFFF;
2024 s_hi = s >> 16;
2025 rlo_lo = a_lo * s_lo;
2026 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2027 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2028 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2029 M.x86.R_EDX = rhi_lo;
2030#endif
2031 if (M.x86.R_EDX == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002032 CLEAR_FLAG(F_CF);
2033 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002034 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002035 SET_FLAG(F_CF);
2036 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002037 }
2038}
2039
2040/****************************************************************************
2041REMARKS:
2042Implements the IDIV instruction and side effects.
2043****************************************************************************/
2044void idiv_byte(u8 s)
2045{
2046 s32 dvd, div, mod;
2047
2048 dvd = (s16)M.x86.R_AX;
2049 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002050 x86emu_intr_raise(0);
2051 return;
Jason Jina63ce952007-07-06 08:34:56 +08002052 }
2053 div = dvd / (s8)s;
2054 mod = dvd % (s8)s;
2055 if (abs(div) > 0x7f) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002056 x86emu_intr_raise(0);
2057 return;
Jason Jina63ce952007-07-06 08:34:56 +08002058 }
2059 M.x86.R_AL = (s8) div;
2060 M.x86.R_AH = (s8) mod;
2061}
2062
2063/****************************************************************************
2064REMARKS:
2065Implements the IDIV instruction and side effects.
2066****************************************************************************/
2067void idiv_word(u16 s)
2068{
2069 s32 dvd, div, mod;
2070
2071 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2072 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002073 x86emu_intr_raise(0);
2074 return;
Jason Jina63ce952007-07-06 08:34:56 +08002075 }
2076 div = dvd / (s16)s;
2077 mod = dvd % (s16)s;
2078 if (abs(div) > 0x7fff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002079 x86emu_intr_raise(0);
2080 return;
Jason Jina63ce952007-07-06 08:34:56 +08002081 }
2082 CLEAR_FLAG(F_CF);
2083 CLEAR_FLAG(F_SF);
2084 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2085 set_parity_flag(mod);
2086
2087 M.x86.R_AX = (u16)div;
2088 M.x86.R_DX = (u16)mod;
2089}
2090
2091/****************************************************************************
2092REMARKS:
2093Implements the IDIV instruction and side effects.
2094****************************************************************************/
2095void idiv_long(u32 s)
2096{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002097#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08002098 s64 dvd, div, mod;
2099
2100 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2101 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002102 x86emu_intr_raise(0);
2103 return;
Jason Jina63ce952007-07-06 08:34:56 +08002104 }
2105 div = dvd / (s32)s;
2106 mod = dvd % (s32)s;
2107 if (abs(div) > 0x7fffffff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002108 x86emu_intr_raise(0);
2109 return;
Jason Jina63ce952007-07-06 08:34:56 +08002110 }
2111#else
2112 s32 div = 0, mod;
2113 s32 h_dvd = M.x86.R_EDX;
2114 u32 l_dvd = M.x86.R_EAX;
2115 u32 abs_s = s & 0x7FFFFFFF;
2116 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2117 u32 h_s = abs_s >> 1;
2118 u32 l_s = abs_s << 31;
2119 int counter = 31;
2120 int carry;
2121
2122 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002123 x86emu_intr_raise(0);
2124 return;
Jason Jina63ce952007-07-06 08:34:56 +08002125 }
2126 do {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002127 div <<= 1;
2128 carry = (l_dvd >= l_s) ? 0 : 1;
Jason Jina63ce952007-07-06 08:34:56 +08002129
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002130 if (abs_h_dvd < (h_s + carry)) {
2131 h_s >>= 1;
2132 l_s = abs_s << (--counter);
2133 continue;
2134 } else {
2135 abs_h_dvd -= (h_s + carry);
2136 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2137 : (l_dvd - l_s);
2138 h_s >>= 1;
2139 l_s = abs_s << (--counter);
2140 div |= 1;
2141 continue;
2142 }
Jason Jina63ce952007-07-06 08:34:56 +08002143
2144 } while (counter > -1);
2145 /* overflow */
2146 if (abs_h_dvd || (l_dvd > abs_s)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002147 x86emu_intr_raise(0);
2148 return;
Jason Jina63ce952007-07-06 08:34:56 +08002149 }
2150 /* sign */
2151 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2152 mod = l_dvd;
2153
2154#endif
2155 CLEAR_FLAG(F_CF);
2156 CLEAR_FLAG(F_AF);
2157 CLEAR_FLAG(F_SF);
2158 SET_FLAG(F_ZF);
2159 set_parity_flag(mod);
2160
2161 M.x86.R_EAX = (u32)div;
2162 M.x86.R_EDX = (u32)mod;
2163}
2164
2165/****************************************************************************
2166REMARKS:
2167Implements the DIV instruction and side effects.
2168****************************************************************************/
2169void div_byte(u8 s)
2170{
2171 u32 dvd, div, mod;
2172
2173 dvd = M.x86.R_AX;
2174 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002175 x86emu_intr_raise(0);
2176 return;
Jason Jina63ce952007-07-06 08:34:56 +08002177 }
2178 div = dvd / (u8)s;
2179 mod = dvd % (u8)s;
2180 if (abs(div) > 0xff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002181 x86emu_intr_raise(0);
2182 return;
Jason Jina63ce952007-07-06 08:34:56 +08002183 }
2184 M.x86.R_AL = (u8)div;
2185 M.x86.R_AH = (u8)mod;
2186}
2187
2188/****************************************************************************
2189REMARKS:
2190Implements the DIV instruction and side effects.
2191****************************************************************************/
2192void div_word(u16 s)
2193{
2194 u32 dvd, div, mod;
2195
2196 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2197 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002198 x86emu_intr_raise(0);
2199 return;
Jason Jina63ce952007-07-06 08:34:56 +08002200 }
2201 div = dvd / (u16)s;
2202 mod = dvd % (u16)s;
2203 if (abs(div) > 0xffff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002204 x86emu_intr_raise(0);
2205 return;
Jason Jina63ce952007-07-06 08:34:56 +08002206 }
2207 CLEAR_FLAG(F_CF);
2208 CLEAR_FLAG(F_SF);
2209 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2210 set_parity_flag(mod);
2211
2212 M.x86.R_AX = (u16)div;
2213 M.x86.R_DX = (u16)mod;
2214}
2215
2216/****************************************************************************
2217REMARKS:
2218Implements the DIV instruction and side effects.
2219****************************************************************************/
2220void div_long(u32 s)
2221{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002222#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08002223 u64 dvd, div, mod;
2224
2225 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2226 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002227 x86emu_intr_raise(0);
2228 return;
Jason Jina63ce952007-07-06 08:34:56 +08002229 }
2230 div = dvd / (u32)s;
2231 mod = dvd % (u32)s;
2232 if (abs(div) > 0xffffffff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002233 x86emu_intr_raise(0);
2234 return;
Jason Jina63ce952007-07-06 08:34:56 +08002235 }
2236#else
2237 s32 div = 0, mod;
2238 s32 h_dvd = M.x86.R_EDX;
2239 u32 l_dvd = M.x86.R_EAX;
2240
2241 u32 h_s = s;
2242 u32 l_s = 0;
2243 int counter = 32;
2244 int carry;
2245
2246 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002247 x86emu_intr_raise(0);
2248 return;
Jason Jina63ce952007-07-06 08:34:56 +08002249 }
2250 do {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002251 div <<= 1;
2252 carry = (l_dvd >= l_s) ? 0 : 1;
Jason Jina63ce952007-07-06 08:34:56 +08002253
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002254 if (h_dvd < (h_s + carry)) {
2255 h_s >>= 1;
2256 l_s = s << (--counter);
2257 continue;
2258 } else {
2259 h_dvd -= (h_s + carry);
2260 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2261 : (l_dvd - l_s);
2262 h_s >>= 1;
2263 l_s = s << (--counter);
2264 div |= 1;
2265 continue;
2266 }
Jason Jina63ce952007-07-06 08:34:56 +08002267
2268 } while (counter > -1);
2269 /* overflow */
2270 if (h_dvd || (l_dvd > s)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002271 x86emu_intr_raise(0);
2272 return;
Jason Jina63ce952007-07-06 08:34:56 +08002273 }
2274 mod = l_dvd;
2275#endif
2276 CLEAR_FLAG(F_CF);
2277 CLEAR_FLAG(F_AF);
2278 CLEAR_FLAG(F_SF);
2279 SET_FLAG(F_ZF);
2280 set_parity_flag(mod);
2281
2282 M.x86.R_EAX = (u32)div;
2283 M.x86.R_EDX = (u32)mod;
2284}
2285
2286/****************************************************************************
2287REMARKS:
2288Implements the IN string instruction and side effects.
2289****************************************************************************/
2290
2291static void single_in(int size)
2292{
2293 if(size == 1)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002294 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
Jason Jina63ce952007-07-06 08:34:56 +08002295 else if (size == 2)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002296 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
Jason Jina63ce952007-07-06 08:34:56 +08002297 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002298 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
Jason Jina63ce952007-07-06 08:34:56 +08002299}
2300
2301void ins(int size)
2302{
2303 int inc = size;
2304
2305 if (ACCESS_FLAG(F_DF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002306 inc = -size;
Jason Jina63ce952007-07-06 08:34:56 +08002307 }
2308 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002309 /* dont care whether REPE or REPNE */
2310 /* in until CX is ZERO. */
2311 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2312 M.x86.R_ECX : M.x86.R_CX);
Jason Jina63ce952007-07-06 08:34:56 +08002313
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002314 while (count--) {
2315 single_in(size);
2316 M.x86.R_DI += inc;
2317 }
2318 M.x86.R_CX = 0;
2319 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2320 M.x86.R_ECX = 0;
2321 }
2322 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002323 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002324 single_in(size);
2325 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002326 }
2327}
2328
2329/****************************************************************************
2330REMARKS:
2331Implements the OUT string instruction and side effects.
2332****************************************************************************/
2333
2334static void single_out(int size)
2335{
2336 if(size == 1)
2337 (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2338 else if (size == 2)
2339 (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2340 else
2341 (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2342}
2343
2344void outs(int size)
2345{
2346 int inc = size;
2347
2348 if (ACCESS_FLAG(F_DF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002349 inc = -size;
Jason Jina63ce952007-07-06 08:34:56 +08002350 }
2351 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002352 /* dont care whether REPE or REPNE */
2353 /* out until CX is ZERO. */
2354 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2355 M.x86.R_ECX : M.x86.R_CX);
2356 while (count--) {
2357 single_out(size);
2358 M.x86.R_SI += inc;
2359 }
2360 M.x86.R_CX = 0;
2361 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2362 M.x86.R_ECX = 0;
2363 }
2364 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002365 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002366 single_out(size);
2367 M.x86.R_SI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002368 }
2369}
2370
2371/****************************************************************************
2372PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002373addr - Address to fetch word from
Jason Jina63ce952007-07-06 08:34:56 +08002374
2375REMARKS:
2376Fetches a word from emulator memory using an absolute address.
2377****************************************************************************/
2378u16 mem_access_word(int addr)
2379{
2380DB( if (CHECK_MEM_ACCESS())
2381 x86emu_check_mem_access(addr);)
2382 return (*sys_rdw)(addr);
2383}
2384
2385/****************************************************************************
2386REMARKS:
2387Pushes a word onto the stack.
2388
2389NOTE: Do not inline this, as (*sys_wrX) is already inline!
2390****************************************************************************/
2391void push_word(u16 w)
2392{
2393DB( if (CHECK_SP_ACCESS())
2394 x86emu_check_sp_access();)
2395 M.x86.R_SP -= 2;
2396 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2397}
2398
2399/****************************************************************************
2400REMARKS:
2401Pushes a long onto the stack.
2402
2403NOTE: Do not inline this, as (*sys_wrX) is already inline!
2404****************************************************************************/
2405void push_long(u32 w)
2406{
2407DB( if (CHECK_SP_ACCESS())
2408 x86emu_check_sp_access();)
2409 M.x86.R_SP -= 4;
2410 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2411}
2412
2413/****************************************************************************
2414REMARKS:
2415Pops a word from the stack.
2416
2417NOTE: Do not inline this, as (*sys_rdX) is already inline!
2418****************************************************************************/
2419u16 pop_word(void)
2420{
2421 u16 res;
2422
2423DB( if (CHECK_SP_ACCESS())
2424 x86emu_check_sp_access();)
2425 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2426 M.x86.R_SP += 2;
2427 return res;
2428}
2429
2430/****************************************************************************
2431REMARKS:
2432Pops a long from the stack.
2433
2434NOTE: Do not inline this, as (*sys_rdX) is already inline!
2435****************************************************************************/
2436u32 pop_long(void)
2437{
2438 u32 res;
2439
2440DB( if (CHECK_SP_ACCESS())
2441 x86emu_check_sp_access();)
2442 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2443 M.x86.R_SP += 4;
2444 return res;
2445}