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