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