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