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