blob: 2a254a4e67139c645acee49550f82ce485cb2cdd [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
Jason Jina63ce952007-07-06 08:34:56 +0800103
Jason Jin7ed5cd92007-08-08 08:33:11 +0800104#if defined(CONFIG_BIOSEMU)
105
Michal Simek952d8612007-08-15 21:15:05 +0200106#include "x86emu/x86emui.h"
107
Jason Jina63ce952007-07-06 08:34:56 +0800108/*------------------------- Global Variables ------------------------------*/
109
110static u32 x86emu_parity_tab[8] =
111{
112 0x96696996,
113 0x69969669,
114 0x69969669,
115 0x96696996,
116 0x69969669,
117 0x96696996,
118 0x96696996,
119 0x69969669,
120};
121
122#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200123#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
Jason Jina63ce952007-07-06 08:34:56 +0800124/*----------------------------- Implementation ----------------------------*/
125int abs(int v)
126{
127 return (v>0)?v:-v;
128}
129
130/*----------------------------- Implementation ----------------------------*/
131
132
133/*--------- Side effects helper functions -------*/
134
135/****************************************************************************
136REMARKS:
137implements side efects for byte operations that don't overflow
138****************************************************************************/
139
140static void set_parity_flag(u32 res)
141{
142 CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
143}
144
145static void set_szp_flags_8(u8 res)
146{
147 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
148 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
149 set_parity_flag(res);
150}
151
152static void set_szp_flags_16(u16 res)
153{
154 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
155 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
156 set_parity_flag(res);
157}
158
159static void set_szp_flags_32(u32 res)
160{
161 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
162 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
163 set_parity_flag(res);
164}
165
166static void no_carry_byte_side_eff(u8 res)
167{
168 CLEAR_FLAG(F_OF);
169 CLEAR_FLAG(F_CF);
170 CLEAR_FLAG(F_AF);
171 set_szp_flags_8(res);
172}
173
174static void no_carry_word_side_eff(u16 res)
175{
176 CLEAR_FLAG(F_OF);
177 CLEAR_FLAG(F_CF);
178 CLEAR_FLAG(F_AF);
179 set_szp_flags_16(res);
180}
181
182static void no_carry_long_side_eff(u32 res)
183{
184 CLEAR_FLAG(F_OF);
185 CLEAR_FLAG(F_CF);
186 CLEAR_FLAG(F_AF);
187 set_szp_flags_32(res);
188}
189
190static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
191{
192 u32 cc;
193
194 cc = (s & d) | ((~res) & (s | d));
195 CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
196 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
197 if (set_carry) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200198 CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800199 }
200}
201
202static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
203{
204 u32 bc;
205
206 bc = (res & (~d | s)) | (~d & s);
207 CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
208 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
209 if (set_carry) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200210 CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800211 }
212}
213
214/****************************************************************************
215REMARKS:
216Implements the AAA instruction and side effects.
217****************************************************************************/
218u16 aaa_word(u16 d)
219{
220 u16 res;
221 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200222 d += 0x6;
223 d += 0x100;
224 SET_FLAG(F_AF);
225 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800226 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200227 CLEAR_FLAG(F_CF);
228 CLEAR_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800229 }
230 res = (u16)(d & 0xFF0F);
231 set_szp_flags_16(res);
232 return res;
233}
234
235/****************************************************************************
236REMARKS:
237Implements the AAA instruction and side effects.
238****************************************************************************/
239u16 aas_word(u16 d)
240{
241 u16 res;
242 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200243 d -= 0x6;
244 d -= 0x100;
245 SET_FLAG(F_AF);
246 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800247 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200248 CLEAR_FLAG(F_CF);
249 CLEAR_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800250 }
251 res = (u16)(d & 0xFF0F);
252 set_szp_flags_16(res);
253 return res;
254}
255
256/****************************************************************************
257REMARKS:
258Implements the AAD instruction and side effects.
259****************************************************************************/
260u16 aad_word(u16 d)
261{
262 u16 l;
263 u8 hb, lb;
264
265 hb = (u8)((d >> 8) & 0xff);
266 lb = (u8)((d & 0xff));
267 l = (u16)((lb + 10 * hb) & 0xFF);
268
269 no_carry_byte_side_eff(l & 0xFF);
270 return l;
271}
272
273/****************************************************************************
274REMARKS:
275Implements the AAM instruction and side effects.
276****************************************************************************/
277u16 aam_word(u8 d)
278{
279 u16 h, l;
280
281 h = (u16)(d / 10);
282 l = (u16)(d % 10);
283 l |= (u16)(h << 8);
284
285 no_carry_byte_side_eff(l & 0xFF);
286 return l;
287}
288
289/****************************************************************************
290REMARKS:
291Implements the ADC instruction and side effects.
292****************************************************************************/
293u8 adc_byte(u8 d, u8 s)
294{
295 u32 res; /* all operands in native machine order */
296
297 res = d + s;
298 if (ACCESS_FLAG(F_CF)) res++;
299
300 set_szp_flags_8(res);
301 calc_carry_chain(8,s,d,res,1);
302
303 return (u8)res;
304}
305
306/****************************************************************************
307REMARKS:
308Implements the ADC instruction and side effects.
309****************************************************************************/
310u16 adc_word(u16 d, u16 s)
311{
312 u32 res; /* all operands in native machine order */
313
314 res = d + s;
315 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200316 res++;
Jason Jina63ce952007-07-06 08:34:56 +0800317
318 set_szp_flags_16((u16)res);
319 calc_carry_chain(16,s,d,res,1);
320
321 return (u16)res;
322}
323
324/****************************************************************************
325REMARKS:
326Implements the ADC instruction and side effects.
327****************************************************************************/
328u32 adc_long(u32 d, u32 s)
329{
330 u32 lo; /* all operands in native machine order */
331 u32 hi;
332 u32 res;
333
334 lo = (d & 0xFFFF) + (s & 0xFFFF);
335 res = d + s;
336
337 if (ACCESS_FLAG(F_CF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200338 lo++;
339 res++;
Jason Jina63ce952007-07-06 08:34:56 +0800340 }
341
342 hi = (lo >> 16) + (d >> 16) + (s >> 16);
343
344 set_szp_flags_32(res);
345 calc_carry_chain(32,s,d,res,0);
346
347 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
348
349 return res;
350}
351
352/****************************************************************************
353REMARKS:
354Implements the ADD instruction and side effects.
355****************************************************************************/
356u8 add_byte(u8 d, u8 s)
357{
358 u32 res; /* all operands in native machine order */
359
360 res = d + s;
361 set_szp_flags_8((u8)res);
362 calc_carry_chain(8,s,d,res,1);
363
364 return (u8)res;
365}
366
367/****************************************************************************
368REMARKS:
369Implements the ADD instruction and side effects.
370****************************************************************************/
371u16 add_word(u16 d, u16 s)
372{
373 u32 res; /* all operands in native machine order */
374
375 res = d + s;
376 set_szp_flags_16((u16)res);
377 calc_carry_chain(16,s,d,res,1);
378
379 return (u16)res;
380}
381
382/****************************************************************************
383REMARKS:
384Implements the ADD instruction and side effects.
385****************************************************************************/
386u32 add_long(u32 d, u32 s)
387{
388 u32 res;
389
390 res = d + s;
391 set_szp_flags_32(res);
392 calc_carry_chain(32,s,d,res,0);
393
394 CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
395
396 return res;
397}
398
399/****************************************************************************
400REMARKS:
401Implements the AND instruction and side effects.
402****************************************************************************/
403u8 and_byte(u8 d, u8 s)
404{
405 u8 res; /* all operands in native machine order */
406
407 res = d & s;
408
409 no_carry_byte_side_eff(res);
410 return res;
411}
412
413/****************************************************************************
414REMARKS:
415Implements the AND instruction and side effects.
416****************************************************************************/
417u16 and_word(u16 d, u16 s)
418{
419 u16 res; /* all operands in native machine order */
420
421 res = d & s;
422
423 no_carry_word_side_eff(res);
424 return res;
425}
426
427/****************************************************************************
428REMARKS:
429Implements the AND instruction and side effects.
430****************************************************************************/
431u32 and_long(u32 d, u32 s)
432{
433 u32 res; /* all operands in native machine order */
434
435 res = d & s;
436 no_carry_long_side_eff(res);
437 return res;
438}
439
440/****************************************************************************
441REMARKS:
442Implements the CMP instruction and side effects.
443****************************************************************************/
444u8 cmp_byte(u8 d, u8 s)
445{
446 u32 res; /* all operands in native machine order */
447
448 res = d - s;
449 set_szp_flags_8((u8)res);
450 calc_borrow_chain(8, d, s, res, 1);
451
452 return d;
453}
454
455/****************************************************************************
456REMARKS:
457Implements the CMP instruction and side effects.
458****************************************************************************/
459u16 cmp_word(u16 d, u16 s)
460{
461 u32 res; /* all operands in native machine order */
462
463 res = d - s;
464 set_szp_flags_16((u16)res);
465 calc_borrow_chain(16, d, s, res, 1);
466
467 return d;
468}
469
470/****************************************************************************
471REMARKS:
472Implements the CMP instruction and side effects.
473****************************************************************************/
474u32 cmp_long(u32 d, u32 s)
475{
476 u32 res; /* all operands in native machine order */
477
478 res = d - s;
479 set_szp_flags_32(res);
480 calc_borrow_chain(32, d, s, res, 1);
481
482 return d;
483}
484
485/****************************************************************************
486REMARKS:
487Implements the DAA instruction and side effects.
488****************************************************************************/
489u8 daa_byte(u8 d)
490{
491 u32 res = d;
492 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200493 res += 6;
494 SET_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800495 }
496 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200497 res += 0x60;
498 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800499 }
500 set_szp_flags_8((u8)res);
501 return (u8)res;
502}
503
504/****************************************************************************
505REMARKS:
506Implements the DAS instruction and side effects.
507****************************************************************************/
508u8 das_byte(u8 d)
509{
510 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200511 d -= 6;
512 SET_FLAG(F_AF);
Jason Jina63ce952007-07-06 08:34:56 +0800513 }
514 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200515 d -= 0x60;
516 SET_FLAG(F_CF);
Jason Jina63ce952007-07-06 08:34:56 +0800517 }
518 set_szp_flags_8(d);
519 return d;
520}
521
522/****************************************************************************
523REMARKS:
524Implements the DEC instruction and side effects.
525****************************************************************************/
526u8 dec_byte(u8 d)
527{
528 u32 res; /* all operands in native machine order */
529
530 res = d - 1;
531 set_szp_flags_8((u8)res);
532 calc_borrow_chain(8, d, 1, res, 0);
533
534 return (u8)res;
535}
536
537/****************************************************************************
538REMARKS:
539Implements the DEC instruction and side effects.
540****************************************************************************/
541u16 dec_word(u16 d)
542{
543 u32 res; /* all operands in native machine order */
544
545 res = d - 1;
546 set_szp_flags_16((u16)res);
547 calc_borrow_chain(16, d, 1, res, 0);
548
549 return (u16)res;
550}
551
552/****************************************************************************
553REMARKS:
554Implements the DEC instruction and side effects.
555****************************************************************************/
556u32 dec_long(u32 d)
557{
558 u32 res; /* all operands in native machine order */
559
560 res = d - 1;
561
562 set_szp_flags_32(res);
563 calc_borrow_chain(32, d, 1, res, 0);
564
565 return res;
566}
567
568/****************************************************************************
569REMARKS:
570Implements the INC instruction and side effects.
571****************************************************************************/
572u8 inc_byte(u8 d)
573{
574 u32 res; /* all operands in native machine order */
575
576 res = d + 1;
577 set_szp_flags_8((u8)res);
578 calc_carry_chain(8, d, 1, res, 0);
579
580 return (u8)res;
581}
582
583/****************************************************************************
584REMARKS:
585Implements the INC instruction and side effects.
586****************************************************************************/
587u16 inc_word(u16 d)
588{
589 u32 res; /* all operands in native machine order */
590
591 res = d + 1;
592 set_szp_flags_16((u16)res);
593 calc_carry_chain(16, d, 1, res, 0);
594
595 return (u16)res;
596}
597
598/****************************************************************************
599REMARKS:
600Implements the INC instruction and side effects.
601****************************************************************************/
602u32 inc_long(u32 d)
603{
604 u32 res; /* all operands in native machine order */
605
606 res = d + 1;
607 set_szp_flags_32(res);
608 calc_carry_chain(32, d, 1, res, 0);
609
610 return res;
611}
612
613/****************************************************************************
614REMARKS:
615Implements the OR instruction and side effects.
616****************************************************************************/
617u8 or_byte(u8 d, u8 s)
618{
619 u8 res; /* all operands in native machine order */
620
621 res = d | s;
622 no_carry_byte_side_eff(res);
623
624 return res;
625}
626
627/****************************************************************************
628REMARKS:
629Implements the OR instruction and side effects.
630****************************************************************************/
631u16 or_word(u16 d, u16 s)
632{
633 u16 res; /* all operands in native machine order */
634
635 res = d | s;
636 no_carry_word_side_eff(res);
637 return res;
638}
639
640/****************************************************************************
641REMARKS:
642Implements the OR instruction and side effects.
643****************************************************************************/
644u32 or_long(u32 d, u32 s)
645{
646 u32 res; /* all operands in native machine order */
647
648 res = d | s;
649 no_carry_long_side_eff(res);
650 return res;
651}
652
653/****************************************************************************
654REMARKS:
655Implements the OR instruction and side effects.
656****************************************************************************/
657u8 neg_byte(u8 s)
658{
659 u8 res;
660
661 CONDITIONAL_SET_FLAG(s != 0, F_CF);
662 res = (u8)-s;
663 set_szp_flags_8(res);
664 calc_borrow_chain(8, 0, s, res, 0);
665
666 return res;
667}
668
669/****************************************************************************
670REMARKS:
671Implements the OR instruction and side effects.
672****************************************************************************/
673u16 neg_word(u16 s)
674{
675 u16 res;
676
677 CONDITIONAL_SET_FLAG(s != 0, F_CF);
678 res = (u16)-s;
679 set_szp_flags_16((u16)res);
680 calc_borrow_chain(16, 0, s, res, 0);
681
682 return res;
683}
684
685/****************************************************************************
686REMARKS:
687Implements the OR instruction and side effects.
688****************************************************************************/
689u32 neg_long(u32 s)
690{
691 u32 res;
692
693 CONDITIONAL_SET_FLAG(s != 0, F_CF);
694 res = (u32)-s;
695 set_szp_flags_32(res);
696 calc_borrow_chain(32, 0, s, res, 0);
697
698 return res;
699}
700
701/****************************************************************************
702REMARKS:
703Implements the NOT instruction and side effects.
704****************************************************************************/
705u8 not_byte(u8 s)
706{
707 return ~s;
708}
709
710/****************************************************************************
711REMARKS:
712Implements the NOT instruction and side effects.
713****************************************************************************/
714u16 not_word(u16 s)
715{
716 return ~s;
717}
718
719/****************************************************************************
720REMARKS:
721Implements the NOT instruction and side effects.
722****************************************************************************/
723u32 not_long(u32 s)
724{
725 return ~s;
726}
727
728/****************************************************************************
729REMARKS:
730Implements the RCL instruction and side effects.
731****************************************************************************/
732u8 rcl_byte(u8 d, u8 s)
733{
734 unsigned int res, cnt, mask, cf;
735
736 /* s is the rotate distance. It varies from 0 - 8. */
737 /* have
738
739 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
740
741 want to rotate through the carry by "s" bits. We could
742 loop, but that's inefficient. So the width is 9,
743 and we split into three parts:
744
745 The new carry flag (was B_n)
746 the stuff in B_n-1 .. B_0
747 the stuff in B_7 .. B_n+1
748
749 The new rotate is done mod 9, and given this,
750 for a rotation of n bits (mod 9) the new carry flag is
751 then located n bits from the MSB. The low part is
752 then shifted up cnt bits, and the high part is or'd
753 in. Using CAPS for new values, and lowercase for the
754 original values, this can be expressed as:
755
756 IF n > 0
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200757 1) CF <- b_(8-n)
Jason Jina63ce952007-07-06 08:34:56 +0800758 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
759 3) B_(n-1) <- cf
760 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
761 */
762 res = d;
763 if ((cnt = s % 9) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200764 /* extract the new CARRY FLAG. */
765 /* CF <- b_(8-n) */
766 cf = (d >> (8 - cnt)) & 0x1;
Jason Jina63ce952007-07-06 08:34:56 +0800767
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200768 /* get the low stuff which rotated
769 into the range B_7 .. B_cnt */
770 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
771 /* note that the right hand side done by the mask */
772 res = (d << cnt) & 0xff;
Jason Jina63ce952007-07-06 08:34:56 +0800773
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200774 /* now the high stuff which rotated around
775 into the positions B_cnt-2 .. B_0 */
776 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
777 /* shift it downward, 7-(n-2) = 9-n positions.
778 and mask off the result before or'ing in.
779 */
780 mask = (1 << (cnt - 1)) - 1;
781 res |= (d >> (9 - cnt)) & mask;
Jason Jina63ce952007-07-06 08:34:56 +0800782
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200783 /* if the carry flag was set, or it in. */
784 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
785 /* B_(n-1) <- cf */
786 res |= 1 << (cnt - 1);
787 }
788 /* set the new carry flag, based on the variable "cf" */
789 CONDITIONAL_SET_FLAG(cf, F_CF);
790 /* OVERFLOW is set *IFF* cnt==1, then it is the
791 xor of CF and the most significant bit. Blecck. */
792 /* parenthesized this expression since it appears to
793 be causing OF to be misset */
794 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
795 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +0800796
797 }
798 return (u8)res;
799}
800
801/****************************************************************************
802REMARKS:
803Implements the RCL instruction and side effects.
804****************************************************************************/
805u16 rcl_word(u16 d, u8 s)
806{
807 unsigned int res, cnt, mask, cf;
808
809 res = d;
810 if ((cnt = s % 17) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200811 cf = (d >> (16 - cnt)) & 0x1;
812 res = (d << cnt) & 0xffff;
813 mask = (1 << (cnt - 1)) - 1;
814 res |= (d >> (17 - cnt)) & mask;
815 if (ACCESS_FLAG(F_CF)) {
816 res |= 1 << (cnt - 1);
817 }
818 CONDITIONAL_SET_FLAG(cf, F_CF);
819 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
820 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +0800821 }
822 return (u16)res;
823}
824
825/****************************************************************************
826REMARKS:
827Implements the RCL instruction and side effects.
828****************************************************************************/
829u32 rcl_long(u32 d, u8 s)
830{
831 u32 res, cnt, mask, cf;
832
833 res = d;
834 if ((cnt = s % 33) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200835 cf = (d >> (32 - cnt)) & 0x1;
836 res = (d << cnt) & 0xffffffff;
837 mask = (1 << (cnt - 1)) - 1;
838 res |= (d >> (33 - cnt)) & mask;
839 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
840 res |= 1 << (cnt - 1);
841 }
842 CONDITIONAL_SET_FLAG(cf, F_CF);
843 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
844 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +0800845 }
846 return res;
847}
848
849/****************************************************************************
850REMARKS:
851Implements the RCR instruction and side effects.
852****************************************************************************/
853u8 rcr_byte(u8 d, u8 s)
854{
855 u32 res, cnt;
856 u32 mask, cf, ocf = 0;
857
858 /* rotate right through carry */
859 /*
860 s is the rotate distance. It varies from 0 - 8.
861 d is the byte object rotated.
862
863 have
864
865 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
866
867 The new rotate is done mod 9, and given this,
868 for a rotation of n bits (mod 9) the new carry flag is
869 then located n bits from the LSB. The low part is
870 then shifted up cnt bits, and the high part is or'd
871 in. Using CAPS for new values, and lowercase for the
872 original values, this can be expressed as:
873
874 IF n > 0
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200875 1) CF <- b_(n-1)
876 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
Jason Jina63ce952007-07-06 08:34:56 +0800877 3) B_(8-n) <- cf
878 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
879 */
880 res = d;
881 if ((cnt = s % 9) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200882 /* extract the new CARRY FLAG. */
883 /* CF <- b_(n-1) */
884 if (cnt == 1) {
885 cf = d & 0x1;
886 /* note hackery here. Access_flag(..) evaluates to either
887 0 if flag not set
888 non-zero if flag is set.
889 doing access_flag(..) != 0 casts that into either
890 0..1 in any representation of the flags register
891 (i.e. packed bit array or unpacked.)
892 */
893 ocf = ACCESS_FLAG(F_CF) != 0;
894 } else
895 cf = (d >> (cnt - 1)) & 0x1;
Jason Jina63ce952007-07-06 08:34:56 +0800896
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200897 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
898 /* note that the right hand side done by the mask
899 This is effectively done by shifting the
900 object to the right. The result must be masked,
901 in case the object came in and was treated
902 as a negative number. Needed??? */
Jason Jina63ce952007-07-06 08:34:56 +0800903
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200904 mask = (1 << (8 - cnt)) - 1;
905 res = (d >> cnt) & mask;
Jason Jina63ce952007-07-06 08:34:56 +0800906
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200907 /* now the high stuff which rotated around
908 into the positions B_cnt-2 .. B_0 */
909 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
910 /* shift it downward, 7-(n-2) = 9-n positions.
911 and mask off the result before or'ing in.
912 */
913 res |= (d << (9 - cnt));
Jason Jina63ce952007-07-06 08:34:56 +0800914
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200915 /* if the carry flag was set, or it in. */
916 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
917 /* B_(8-n) <- cf */
918 res |= 1 << (8 - cnt);
919 }
920 /* set the new carry flag, based on the variable "cf" */
921 CONDITIONAL_SET_FLAG(cf, F_CF);
922 /* OVERFLOW is set *IFF* cnt==1, then it is the
923 xor of CF and the most significant bit. Blecck. */
924 /* parenthesized... */
925 if (cnt == 1) {
926 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
927 F_OF);
928 }
Jason Jina63ce952007-07-06 08:34:56 +0800929 }
930 return (u8)res;
931}
932
933/****************************************************************************
934REMARKS:
935Implements the RCR instruction and side effects.
936****************************************************************************/
937u16 rcr_word(u16 d, u8 s)
938{
939 u32 res, cnt;
940 u32 mask, cf, ocf = 0;
941
942 /* rotate right through carry */
943 res = d;
944 if ((cnt = s % 17) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200945 if (cnt == 1) {
946 cf = d & 0x1;
947 ocf = ACCESS_FLAG(F_CF) != 0;
948 } else
949 cf = (d >> (cnt - 1)) & 0x1;
950 mask = (1 << (16 - cnt)) - 1;
951 res = (d >> cnt) & mask;
952 res |= (d << (17 - cnt));
953 if (ACCESS_FLAG(F_CF)) {
954 res |= 1 << (16 - cnt);
955 }
956 CONDITIONAL_SET_FLAG(cf, F_CF);
957 if (cnt == 1) {
958 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
959 F_OF);
960 }
Jason Jina63ce952007-07-06 08:34:56 +0800961 }
962 return (u16)res;
963}
964
965/****************************************************************************
966REMARKS:
967Implements the RCR instruction and side effects.
968****************************************************************************/
969u32 rcr_long(u32 d, u8 s)
970{
971 u32 res, cnt;
972 u32 mask, cf, ocf = 0;
973
974 /* rotate right through carry */
975 res = d;
976 if ((cnt = s % 33) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200977 if (cnt == 1) {
978 cf = d & 0x1;
979 ocf = ACCESS_FLAG(F_CF) != 0;
980 } else
981 cf = (d >> (cnt - 1)) & 0x1;
982 mask = (1 << (32 - cnt)) - 1;
983 res = (d >> cnt) & mask;
984 if (cnt != 1)
985 res |= (d << (33 - cnt));
986 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
987 res |= 1 << (32 - cnt);
988 }
989 CONDITIONAL_SET_FLAG(cf, F_CF);
990 if (cnt == 1) {
991 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
992 F_OF);
993 }
Jason Jina63ce952007-07-06 08:34:56 +0800994 }
995 return res;
996}
997
998/****************************************************************************
999REMARKS:
1000Implements the ROL instruction and side effects.
1001****************************************************************************/
1002u8 rol_byte(u8 d, u8 s)
1003{
1004 unsigned int res, cnt, mask;
1005
1006 /* rotate left */
1007 /*
1008 s is the rotate distance. It varies from 0 - 8.
1009 d is the byte object rotated.
1010
1011 have
1012
1013 CF B_7 ... B_0
1014
1015 The new rotate is done mod 8.
1016 Much simpler than the "rcl" or "rcr" operations.
1017
1018 IF n > 0
1019 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1020 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1021 */
1022 res = d;
1023 if ((cnt = s % 8) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001024 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1025 res = (d << cnt);
Jason Jina63ce952007-07-06 08:34:56 +08001026
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001027 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1028 mask = (1 << cnt) - 1;
1029 res |= (d >> (8 - cnt)) & mask;
Jason Jina63ce952007-07-06 08:34:56 +08001030
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001031 /* set the new carry flag, Note that it is the low order
1032 bit of the result!!! */
1033 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1034 /* OVERFLOW is set *IFF* s==1, then it is the
1035 xor of CF and the most significant bit. Blecck. */
1036 CONDITIONAL_SET_FLAG(s == 1 &&
1037 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1038 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001039 } if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001040 /* set the new carry flag, Note that it is the low order
1041 bit of the result!!! */
1042 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001043 }
1044 return (u8)res;
1045}
1046
1047/****************************************************************************
1048REMARKS:
1049Implements the ROL instruction and side effects.
1050****************************************************************************/
1051u16 rol_word(u16 d, u8 s)
1052{
1053 unsigned int res, cnt, mask;
1054
1055 res = d;
1056 if ((cnt = s % 16) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001057 res = (d << cnt);
1058 mask = (1 << cnt) - 1;
1059 res |= (d >> (16 - cnt)) & mask;
1060 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1061 CONDITIONAL_SET_FLAG(s == 1 &&
1062 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1063 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001064 } if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001065 /* set the new carry flag, Note that it is the low order
1066 bit of the result!!! */
1067 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001068 }
1069 return (u16)res;
1070}
1071
1072/****************************************************************************
1073REMARKS:
1074Implements the ROL instruction and side effects.
1075****************************************************************************/
1076u32 rol_long(u32 d, u8 s)
1077{
1078 u32 res, cnt, mask;
1079
1080 res = d;
1081 if ((cnt = s % 32) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001082 res = (d << cnt);
1083 mask = (1 << cnt) - 1;
1084 res |= (d >> (32 - cnt)) & mask;
1085 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1086 CONDITIONAL_SET_FLAG(s == 1 &&
1087 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1088 F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001089 } if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001090 /* set the new carry flag, Note that it is the low order
1091 bit of the result!!! */
1092 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001093 }
1094 return res;
1095}
1096
1097/****************************************************************************
1098REMARKS:
1099Implements the ROR instruction and side effects.
1100****************************************************************************/
1101u8 ror_byte(u8 d, u8 s)
1102{
1103 unsigned int res, cnt, mask;
1104
1105 /* rotate right */
1106 /*
1107 s is the rotate distance. It varies from 0 - 8.
1108 d is the byte object rotated.
1109
1110 have
1111
1112 B_7 ... B_0
1113
1114 The rotate is done mod 8.
1115
1116 IF n > 0
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001117 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
Jason Jina63ce952007-07-06 08:34:56 +08001118 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1119 */
1120 res = d;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001121 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
1122 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1123 res = (d << (8 - cnt));
Jason Jina63ce952007-07-06 08:34:56 +08001124
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001125 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1126 mask = (1 << (8 - cnt)) - 1;
1127 res |= (d >> (cnt)) & mask;
Jason Jina63ce952007-07-06 08:34:56 +08001128
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001129 /* set the new carry flag, Note that it is the low order
1130 bit of the result!!! */
1131 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1132 /* OVERFLOW is set *IFF* s==1, then it is the
1133 xor of the two most significant bits. Blecck. */
1134 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001135 } else if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001136 /* set the new carry flag, Note that it is the low order
1137 bit of the result!!! */
1138 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001139 }
1140 return (u8)res;
1141}
1142
1143/****************************************************************************
1144REMARKS:
1145Implements the ROR instruction and side effects.
1146****************************************************************************/
1147u16 ror_word(u16 d, u8 s)
1148{
1149 unsigned int res, cnt, mask;
1150
1151 res = d;
1152 if ((cnt = s % 16) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001153 res = (d << (16 - cnt));
1154 mask = (1 << (16 - cnt)) - 1;
1155 res |= (d >> (cnt)) & mask;
1156 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1157 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001158 } else if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001159 /* set the new carry flag, Note that it is the low order
1160 bit of the result!!! */
1161 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001162 }
1163 return (u16)res;
1164}
1165
1166/****************************************************************************
1167REMARKS:
1168Implements the ROR instruction and side effects.
1169****************************************************************************/
1170u32 ror_long(u32 d, u8 s)
1171{
1172 u32 res, cnt, mask;
1173
1174 res = d;
1175 if ((cnt = s % 32) != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001176 res = (d << (32 - cnt));
1177 mask = (1 << (32 - cnt)) - 1;
1178 res |= (d >> (cnt)) & mask;
1179 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1180 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001181 } else if (s != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001182 /* set the new carry flag, Note that it is the low order
1183 bit of the result!!! */
1184 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
Jason Jina63ce952007-07-06 08:34:56 +08001185 }
1186 return res;
1187}
1188
1189/****************************************************************************
1190REMARKS:
1191Implements the SHL instruction and side effects.
1192****************************************************************************/
1193u8 shl_byte(u8 d, u8 s)
1194{
1195 unsigned int cnt, res, cf;
1196
1197 if (s < 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001198 cnt = s % 8;
Jason Jina63ce952007-07-06 08:34:56 +08001199
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001200 /* last bit shifted out goes into carry flag */
1201 if (cnt > 0) {
1202 res = d << cnt;
1203 cf = d & (1 << (8 - cnt));
1204 CONDITIONAL_SET_FLAG(cf, F_CF);
1205 set_szp_flags_8((u8)res);
1206 } else {
1207 res = (u8) d;
1208 }
Jason Jina63ce952007-07-06 08:34:56 +08001209
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001210 if (cnt == 1) {
1211 /* Needs simplification. */
1212 CONDITIONAL_SET_FLAG(
1213 (((res & 0x80) == 0x80) ^
1214 (ACCESS_FLAG(F_CF) != 0)),
1215 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1216 F_OF);
1217 } else {
1218 CLEAR_FLAG(F_OF);
1219 }
Jason Jina63ce952007-07-06 08:34:56 +08001220 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001221 res = 0;
1222 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1223 CLEAR_FLAG(F_OF);
1224 CLEAR_FLAG(F_SF);
1225 SET_FLAG(F_PF);
1226 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001227 }
1228 return (u8)res;
1229}
1230
1231/****************************************************************************
1232REMARKS:
1233Implements the SHL instruction and side effects.
1234****************************************************************************/
1235u16 shl_word(u16 d, u8 s)
1236{
1237 unsigned int cnt, res, cf;
1238
1239 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001240 cnt = s % 16;
1241 if (cnt > 0) {
1242 res = d << cnt;
1243 cf = d & (1 << (16 - cnt));
1244 CONDITIONAL_SET_FLAG(cf, F_CF);
1245 set_szp_flags_16((u16)res);
1246 } else {
1247 res = (u16) d;
1248 }
Jason Jina63ce952007-07-06 08:34:56 +08001249
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001250 if (cnt == 1) {
1251 CONDITIONAL_SET_FLAG(
1252 (((res & 0x8000) == 0x8000) ^
1253 (ACCESS_FLAG(F_CF) != 0)),
1254 F_OF);
1255 } else {
1256 CLEAR_FLAG(F_OF);
1257 }
Jason Jina63ce952007-07-06 08:34:56 +08001258 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001259 res = 0;
1260 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1261 CLEAR_FLAG(F_OF);
1262 CLEAR_FLAG(F_SF);
1263 SET_FLAG(F_PF);
1264 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001265 }
1266 return (u16)res;
1267}
1268
1269/****************************************************************************
1270REMARKS:
1271Implements the SHL instruction and side effects.
1272****************************************************************************/
1273u32 shl_long(u32 d, u8 s)
1274{
1275 unsigned int cnt, res, cf;
1276
1277 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001278 cnt = s % 32;
1279 if (cnt > 0) {
1280 res = d << cnt;
1281 cf = d & (1 << (32 - cnt));
1282 CONDITIONAL_SET_FLAG(cf, F_CF);
1283 set_szp_flags_32((u32)res);
1284 } else {
1285 res = d;
1286 }
1287 if (cnt == 1) {
1288 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1289 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1290 } else {
1291 CLEAR_FLAG(F_OF);
1292 }
Jason Jina63ce952007-07-06 08:34:56 +08001293 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001294 res = 0;
1295 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1296 CLEAR_FLAG(F_OF);
1297 CLEAR_FLAG(F_SF);
1298 SET_FLAG(F_PF);
1299 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001300 }
1301 return res;
1302}
1303
1304/****************************************************************************
1305REMARKS:
1306Implements the SHR instruction and side effects.
1307****************************************************************************/
1308u8 shr_byte(u8 d, u8 s)
1309{
1310 unsigned int cnt, res, cf;
1311
1312 if (s < 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001313 cnt = s % 8;
1314 if (cnt > 0) {
1315 cf = d & (1 << (cnt - 1));
1316 res = d >> cnt;
1317 CONDITIONAL_SET_FLAG(cf, F_CF);
1318 set_szp_flags_8((u8)res);
1319 } else {
1320 res = (u8) d;
1321 }
Jason Jina63ce952007-07-06 08:34:56 +08001322
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001323 if (cnt == 1) {
1324 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1325 } else {
1326 CLEAR_FLAG(F_OF);
1327 }
Jason Jina63ce952007-07-06 08:34:56 +08001328 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001329 res = 0;
1330 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1331 CLEAR_FLAG(F_OF);
1332 CLEAR_FLAG(F_SF);
1333 SET_FLAG(F_PF);
1334 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001335 }
1336 return (u8)res;
1337}
1338
1339/****************************************************************************
1340REMARKS:
1341Implements the SHR instruction and side effects.
1342****************************************************************************/
1343u16 shr_word(u16 d, u8 s)
1344{
1345 unsigned int cnt, res, cf;
1346
1347 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001348 cnt = s % 16;
1349 if (cnt > 0) {
1350 cf = d & (1 << (cnt - 1));
1351 res = d >> cnt;
1352 CONDITIONAL_SET_FLAG(cf, F_CF);
1353 set_szp_flags_16((u16)res);
1354 } else {
1355 res = d;
1356 }
Jason Jina63ce952007-07-06 08:34:56 +08001357
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001358 if (cnt == 1) {
1359 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1360 } else {
1361 CLEAR_FLAG(F_OF);
1362 }
Jason Jina63ce952007-07-06 08:34:56 +08001363 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001364 res = 0;
1365 CLEAR_FLAG(F_CF);
1366 CLEAR_FLAG(F_OF);
1367 SET_FLAG(F_ZF);
1368 CLEAR_FLAG(F_SF);
1369 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001370 }
1371 return (u16)res;
1372}
1373
1374/****************************************************************************
1375REMARKS:
1376Implements the SHR instruction and side effects.
1377****************************************************************************/
1378u32 shr_long(u32 d, u8 s)
1379{
1380 unsigned int cnt, res, cf;
1381
1382 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001383 cnt = s % 32;
1384 if (cnt > 0) {
1385 cf = d & (1 << (cnt - 1));
1386 res = d >> cnt;
1387 CONDITIONAL_SET_FLAG(cf, F_CF);
1388 set_szp_flags_32((u32)res);
1389 } else {
1390 res = d;
1391 }
1392 if (cnt == 1) {
1393 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1394 } else {
1395 CLEAR_FLAG(F_OF);
1396 }
Jason Jina63ce952007-07-06 08:34:56 +08001397 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001398 res = 0;
1399 CLEAR_FLAG(F_CF);
1400 CLEAR_FLAG(F_OF);
1401 SET_FLAG(F_ZF);
1402 CLEAR_FLAG(F_SF);
1403 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001404 }
1405 return res;
1406}
1407
1408/****************************************************************************
1409REMARKS:
1410Implements the SAR instruction and side effects.
1411****************************************************************************/
1412u8 sar_byte(u8 d, u8 s)
1413{
1414 unsigned int cnt, res, cf, mask, sf;
1415
1416 res = d;
1417 sf = d & 0x80;
1418 cnt = s % 8;
1419 if (cnt > 0 && cnt < 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001420 mask = (1 << (8 - cnt)) - 1;
1421 cf = d & (1 << (cnt - 1));
1422 res = (d >> cnt) & mask;
1423 CONDITIONAL_SET_FLAG(cf, F_CF);
1424 if (sf) {
1425 res |= ~mask;
1426 }
1427 set_szp_flags_8((u8)res);
Jason Jina63ce952007-07-06 08:34:56 +08001428 } else if (cnt >= 8) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001429 if (sf) {
1430 res = 0xff;
1431 SET_FLAG(F_CF);
1432 CLEAR_FLAG(F_ZF);
1433 SET_FLAG(F_SF);
1434 SET_FLAG(F_PF);
1435 } else {
1436 res = 0;
1437 CLEAR_FLAG(F_CF);
1438 SET_FLAG(F_ZF);
1439 CLEAR_FLAG(F_SF);
1440 CLEAR_FLAG(F_PF);
1441 }
Jason Jina63ce952007-07-06 08:34:56 +08001442 }
1443 return (u8)res;
1444}
1445
1446/****************************************************************************
1447REMARKS:
1448Implements the SAR instruction and side effects.
1449****************************************************************************/
1450u16 sar_word(u16 d, u8 s)
1451{
1452 unsigned int cnt, res, cf, mask, sf;
1453
1454 sf = d & 0x8000;
1455 cnt = s % 16;
1456 res = d;
1457 if (cnt > 0 && cnt < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001458 mask = (1 << (16 - cnt)) - 1;
1459 cf = d & (1 << (cnt - 1));
1460 res = (d >> cnt) & mask;
1461 CONDITIONAL_SET_FLAG(cf, F_CF);
1462 if (sf) {
1463 res |= ~mask;
1464 }
1465 set_szp_flags_16((u16)res);
Jason Jina63ce952007-07-06 08:34:56 +08001466 } else if (cnt >= 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001467 if (sf) {
1468 res = 0xffff;
1469 SET_FLAG(F_CF);
1470 CLEAR_FLAG(F_ZF);
1471 SET_FLAG(F_SF);
1472 SET_FLAG(F_PF);
1473 } else {
1474 res = 0;
1475 CLEAR_FLAG(F_CF);
1476 SET_FLAG(F_ZF);
1477 CLEAR_FLAG(F_SF);
1478 CLEAR_FLAG(F_PF);
1479 }
Jason Jina63ce952007-07-06 08:34:56 +08001480 }
1481 return (u16)res;
1482}
1483
1484/****************************************************************************
1485REMARKS:
1486Implements the SAR instruction and side effects.
1487****************************************************************************/
1488u32 sar_long(u32 d, u8 s)
1489{
1490 u32 cnt, res, cf, mask, sf;
1491
1492 sf = d & 0x80000000;
1493 cnt = s % 32;
1494 res = d;
1495 if (cnt > 0 && cnt < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001496 mask = (1 << (32 - cnt)) - 1;
1497 cf = d & (1 << (cnt - 1));
1498 res = (d >> cnt) & mask;
1499 CONDITIONAL_SET_FLAG(cf, F_CF);
1500 if (sf) {
1501 res |= ~mask;
1502 }
1503 set_szp_flags_32(res);
Jason Jina63ce952007-07-06 08:34:56 +08001504 } else if (cnt >= 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001505 if (sf) {
1506 res = 0xffffffff;
1507 SET_FLAG(F_CF);
1508 CLEAR_FLAG(F_ZF);
1509 SET_FLAG(F_SF);
1510 SET_FLAG(F_PF);
1511 } else {
1512 res = 0;
1513 CLEAR_FLAG(F_CF);
1514 SET_FLAG(F_ZF);
1515 CLEAR_FLAG(F_SF);
1516 CLEAR_FLAG(F_PF);
1517 }
Jason Jina63ce952007-07-06 08:34:56 +08001518 }
1519 return res;
1520}
1521
1522/****************************************************************************
1523REMARKS:
1524Implements the SHLD instruction and side effects.
1525****************************************************************************/
1526u16 shld_word (u16 d, u16 fill, u8 s)
1527{
1528 unsigned int cnt, res, cf;
1529
1530 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001531 cnt = s % 16;
1532 if (cnt > 0) {
1533 res = (d << cnt) | (fill >> (16-cnt));
1534 cf = d & (1 << (16 - cnt));
1535 CONDITIONAL_SET_FLAG(cf, F_CF);
1536 set_szp_flags_16((u16)res);
1537 } else {
1538 res = d;
1539 }
1540 if (cnt == 1) {
1541 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1542 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1543 } else {
1544 CLEAR_FLAG(F_OF);
1545 }
Jason Jina63ce952007-07-06 08:34:56 +08001546 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001547 res = 0;
1548 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1549 CLEAR_FLAG(F_OF);
1550 CLEAR_FLAG(F_SF);
1551 SET_FLAG(F_PF);
1552 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001553 }
1554 return (u16)res;
1555}
1556
1557/****************************************************************************
1558REMARKS:
1559Implements the SHLD instruction and side effects.
1560****************************************************************************/
1561u32 shld_long (u32 d, u32 fill, u8 s)
1562{
1563 unsigned int cnt, res, cf;
1564
1565 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001566 cnt = s % 32;
1567 if (cnt > 0) {
1568 res = (d << cnt) | (fill >> (32-cnt));
1569 cf = d & (1 << (32 - cnt));
1570 CONDITIONAL_SET_FLAG(cf, F_CF);
1571 set_szp_flags_32((u32)res);
1572 } else {
1573 res = d;
1574 }
1575 if (cnt == 1) {
1576 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1577 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1578 } else {
1579 CLEAR_FLAG(F_OF);
1580 }
Jason Jina63ce952007-07-06 08:34:56 +08001581 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001582 res = 0;
1583 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1584 CLEAR_FLAG(F_OF);
1585 CLEAR_FLAG(F_SF);
1586 SET_FLAG(F_PF);
1587 SET_FLAG(F_ZF);
Jason Jina63ce952007-07-06 08:34:56 +08001588 }
1589 return res;
1590}
1591
1592/****************************************************************************
1593REMARKS:
1594Implements the SHRD instruction and side effects.
1595****************************************************************************/
1596u16 shrd_word (u16 d, u16 fill, u8 s)
1597{
1598 unsigned int cnt, res, cf;
1599
1600 if (s < 16) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001601 cnt = s % 16;
1602 if (cnt > 0) {
1603 cf = d & (1 << (cnt - 1));
1604 res = (d >> cnt) | (fill << (16 - cnt));
1605 CONDITIONAL_SET_FLAG(cf, F_CF);
1606 set_szp_flags_16((u16)res);
1607 } else {
1608 res = d;
1609 }
Jason Jina63ce952007-07-06 08:34:56 +08001610
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001611 if (cnt == 1) {
1612 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1613 } else {
1614 CLEAR_FLAG(F_OF);
1615 }
Jason Jina63ce952007-07-06 08:34:56 +08001616 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001617 res = 0;
1618 CLEAR_FLAG(F_CF);
1619 CLEAR_FLAG(F_OF);
1620 SET_FLAG(F_ZF);
1621 CLEAR_FLAG(F_SF);
1622 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001623 }
1624 return (u16)res;
1625}
1626
1627/****************************************************************************
1628REMARKS:
1629Implements the SHRD instruction and side effects.
1630****************************************************************************/
1631u32 shrd_long (u32 d, u32 fill, u8 s)
1632{
1633 unsigned int cnt, res, cf;
1634
1635 if (s < 32) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001636 cnt = s % 32;
1637 if (cnt > 0) {
1638 cf = d & (1 << (cnt - 1));
1639 res = (d >> cnt) | (fill << (32 - cnt));
1640 CONDITIONAL_SET_FLAG(cf, F_CF);
1641 set_szp_flags_32((u32)res);
1642 } else {
1643 res = d;
1644 }
1645 if (cnt == 1) {
1646 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1647 } else {
1648 CLEAR_FLAG(F_OF);
1649 }
Jason Jina63ce952007-07-06 08:34:56 +08001650 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001651 res = 0;
1652 CLEAR_FLAG(F_CF);
1653 CLEAR_FLAG(F_OF);
1654 SET_FLAG(F_ZF);
1655 CLEAR_FLAG(F_SF);
1656 CLEAR_FLAG(F_PF);
Jason Jina63ce952007-07-06 08:34:56 +08001657 }
1658 return res;
1659}
1660
1661/****************************************************************************
1662REMARKS:
1663Implements the SBB instruction and side effects.
1664****************************************************************************/
1665u8 sbb_byte(u8 d, u8 s)
1666{
1667 u32 res; /* all operands in native machine order */
1668 u32 bc;
1669
1670 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001671 res = d - s - 1;
Jason Jina63ce952007-07-06 08:34:56 +08001672 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001673 res = d - s;
Jason Jina63ce952007-07-06 08:34:56 +08001674 set_szp_flags_8((u8)res);
1675
1676 /* calculate the borrow chain. See note at top */
1677 bc = (res & (~d | s)) | (~d & s);
1678 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1679 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1680 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1681 return (u8)res;
1682}
1683
1684/****************************************************************************
1685REMARKS:
1686Implements the SBB instruction and side effects.
1687****************************************************************************/
1688u16 sbb_word(u16 d, u16 s)
1689{
1690 u32 res; /* all operands in native machine order */
1691 u32 bc;
1692
1693 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001694 res = d - s - 1;
Jason Jina63ce952007-07-06 08:34:56 +08001695 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001696 res = d - s;
Jason Jina63ce952007-07-06 08:34:56 +08001697 set_szp_flags_16((u16)res);
1698
1699 /* calculate the borrow chain. See note at top */
1700 bc = (res & (~d | s)) | (~d & s);
1701 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1702 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1703 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1704 return (u16)res;
1705}
1706
1707/****************************************************************************
1708REMARKS:
1709Implements the SBB instruction and side effects.
1710****************************************************************************/
1711u32 sbb_long(u32 d, u32 s)
1712{
1713 u32 res; /* all operands in native machine order */
1714 u32 bc;
1715
1716 if (ACCESS_FLAG(F_CF))
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001717 res = d - s - 1;
Jason Jina63ce952007-07-06 08:34:56 +08001718 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001719 res = d - s;
Jason Jina63ce952007-07-06 08:34:56 +08001720
1721 set_szp_flags_32(res);
1722
1723 /* calculate the borrow chain. See note at top */
1724 bc = (res & (~d | s)) | (~d & s);
1725 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1726 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1727 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1728 return res;
1729}
1730
1731/****************************************************************************
1732REMARKS:
1733Implements the SUB instruction and side effects.
1734****************************************************************************/
1735u8 sub_byte(u8 d, u8 s)
1736{
1737 u32 res; /* all operands in native machine order */
1738 u32 bc;
1739
1740 res = d - s;
1741 set_szp_flags_8((u8)res);
1742
1743 /* calculate the borrow chain. See note at top */
1744 bc = (res & (~d | s)) | (~d & s);
1745 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1746 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1747 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1748 return (u8)res;
1749}
1750
1751/****************************************************************************
1752REMARKS:
1753Implements the SUB instruction and side effects.
1754****************************************************************************/
1755u16 sub_word(u16 d, u16 s)
1756{
1757 u32 res; /* all operands in native machine order */
1758 u32 bc;
1759
1760 res = d - s;
1761 set_szp_flags_16((u16)res);
1762
1763 /* calculate the borrow chain. See note at top */
1764 bc = (res & (~d | s)) | (~d & s);
1765 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1766 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1767 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1768 return (u16)res;
1769}
1770
1771/****************************************************************************
1772REMARKS:
1773Implements the SUB instruction and side effects.
1774****************************************************************************/
1775u32 sub_long(u32 d, u32 s)
1776{
1777 u32 res; /* all operands in native machine order */
1778 u32 bc;
1779
1780 res = d - s;
1781 set_szp_flags_32(res);
1782
1783 /* calculate the borrow chain. See note at top */
1784 bc = (res & (~d | s)) | (~d & s);
1785 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1786 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1787 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1788 return res;
1789}
1790
1791/****************************************************************************
1792REMARKS:
1793Implements the TEST instruction and side effects.
1794****************************************************************************/
1795void test_byte(u8 d, u8 s)
1796{
1797 u32 res; /* all operands in native machine order */
1798
1799 res = d & s;
1800
1801 CLEAR_FLAG(F_OF);
1802 set_szp_flags_8((u8)res);
1803 /* AF == dont care */
1804 CLEAR_FLAG(F_CF);
1805}
1806
1807/****************************************************************************
1808REMARKS:
1809Implements the TEST instruction and side effects.
1810****************************************************************************/
1811void test_word(u16 d, u16 s)
1812{
1813 u32 res; /* all operands in native machine order */
1814
1815 res = d & s;
1816
1817 CLEAR_FLAG(F_OF);
1818 set_szp_flags_16((u16)res);
1819 /* AF == dont care */
1820 CLEAR_FLAG(F_CF);
1821}
1822
1823/****************************************************************************
1824REMARKS:
1825Implements the TEST instruction and side effects.
1826****************************************************************************/
1827void test_long(u32 d, u32 s)
1828{
1829 u32 res; /* all operands in native machine order */
1830
1831 res = d & s;
1832
1833 CLEAR_FLAG(F_OF);
1834 set_szp_flags_32(res);
1835 /* AF == dont care */
1836 CLEAR_FLAG(F_CF);
1837}
1838
1839/****************************************************************************
1840REMARKS:
1841Implements the XOR instruction and side effects.
1842****************************************************************************/
1843u8 xor_byte(u8 d, u8 s)
1844{
1845 u8 res; /* all operands in native machine order */
1846
1847 res = d ^ s;
1848 no_carry_byte_side_eff(res);
1849 return res;
1850}
1851
1852/****************************************************************************
1853REMARKS:
1854Implements the XOR instruction and side effects.
1855****************************************************************************/
1856u16 xor_word(u16 d, u16 s)
1857{
1858 u16 res; /* all operands in native machine order */
1859
1860 res = d ^ s;
1861 no_carry_word_side_eff(res);
1862 return res;
1863}
1864
1865/****************************************************************************
1866REMARKS:
1867Implements the XOR instruction and side effects.
1868****************************************************************************/
1869u32 xor_long(u32 d, u32 s)
1870{
1871 u32 res; /* all operands in native machine order */
1872
1873 res = d ^ s;
1874 no_carry_long_side_eff(res);
1875 return res;
1876}
1877
1878/****************************************************************************
1879REMARKS:
1880Implements the IMUL instruction and side effects.
1881****************************************************************************/
1882void imul_byte(u8 s)
1883{
1884 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1885
1886 M.x86.R_AX = res;
1887 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001888 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
1889 CLEAR_FLAG(F_CF);
1890 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001891 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001892 SET_FLAG(F_CF);
1893 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001894 }
1895}
1896
1897/****************************************************************************
1898REMARKS:
1899Implements the IMUL instruction and side effects.
1900****************************************************************************/
1901void imul_word(u16 s)
1902{
1903 s32 res = (s16)M.x86.R_AX * (s16)s;
1904
1905 M.x86.R_AX = (u16)res;
1906 M.x86.R_DX = (u16)(res >> 16);
1907 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001908 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
1909 CLEAR_FLAG(F_CF);
1910 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001911 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001912 SET_FLAG(F_CF);
1913 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001914 }
1915}
1916
1917/****************************************************************************
1918REMARKS:
1919Implements the IMUL instruction and side effects.
1920****************************************************************************/
1921void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1922{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001923#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08001924 s64 res = (s32)d * (s32)s;
1925
1926 *res_lo = (u32)res;
1927 *res_hi = (u32)(res >> 32);
1928#else
1929 u32 d_lo,d_hi,d_sign;
1930 u32 s_lo,s_hi,s_sign;
1931 u32 rlo_lo,rlo_hi,rhi_lo;
1932
1933 if ((d_sign = d & 0x80000000) != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001934 d = -d;
Jason Jina63ce952007-07-06 08:34:56 +08001935 d_lo = d & 0xFFFF;
1936 d_hi = d >> 16;
1937 if ((s_sign = s & 0x80000000) != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001938 s = -s;
Jason Jina63ce952007-07-06 08:34:56 +08001939 s_lo = s & 0xFFFF;
1940 s_hi = s >> 16;
1941 rlo_lo = d_lo * s_lo;
1942 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
1943 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
1944 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
1945 *res_hi = rhi_lo;
1946 if (d_sign != s_sign) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001947 d = ~*res_lo;
1948 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1949 *res_lo = ~*res_lo+1;
1950 *res_hi = ~*res_hi+(s >> 16);
1951 }
Jason Jina63ce952007-07-06 08:34:56 +08001952#endif
1953}
1954
1955/****************************************************************************
1956REMARKS:
1957Implements the IMUL instruction and side effects.
1958****************************************************************************/
1959void imul_long(u32 s)
1960{
1961 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
1962 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001963 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
1964 CLEAR_FLAG(F_CF);
1965 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001966 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001967 SET_FLAG(F_CF);
1968 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001969 }
1970}
1971
1972/****************************************************************************
1973REMARKS:
1974Implements the MUL instruction and side effects.
1975****************************************************************************/
1976void mul_byte(u8 s)
1977{
1978 u16 res = (u16)(M.x86.R_AL * s);
1979
1980 M.x86.R_AX = res;
1981 if (M.x86.R_AH == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001982 CLEAR_FLAG(F_CF);
1983 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001984 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001985 SET_FLAG(F_CF);
1986 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08001987 }
1988}
1989
1990/****************************************************************************
1991REMARKS:
1992Implements the MUL instruction and side effects.
1993****************************************************************************/
1994void mul_word(u16 s)
1995{
1996 u32 res = M.x86.R_AX * s;
1997
1998 M.x86.R_AX = (u16)res;
1999 M.x86.R_DX = (u16)(res >> 16);
2000 if (M.x86.R_DX == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002001 CLEAR_FLAG(F_CF);
2002 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002003 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002004 SET_FLAG(F_CF);
2005 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002006 }
2007}
2008
2009/****************************************************************************
2010REMARKS:
2011Implements the MUL instruction and side effects.
2012****************************************************************************/
2013void mul_long(u32 s)
2014{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002015#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08002016 u64 res = (u32)M.x86.R_EAX * (u32)s;
2017
2018 M.x86.R_EAX = (u32)res;
2019 M.x86.R_EDX = (u32)(res >> 32);
2020#else
2021 u32 a,a_lo,a_hi;
2022 u32 s_lo,s_hi;
2023 u32 rlo_lo,rlo_hi,rhi_lo;
2024
2025 a = M.x86.R_EAX;
2026 a_lo = a & 0xFFFF;
2027 a_hi = a >> 16;
2028 s_lo = s & 0xFFFF;
2029 s_hi = s >> 16;
2030 rlo_lo = a_lo * s_lo;
2031 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2032 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2033 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2034 M.x86.R_EDX = rhi_lo;
2035#endif
2036 if (M.x86.R_EDX == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002037 CLEAR_FLAG(F_CF);
2038 CLEAR_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002039 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002040 SET_FLAG(F_CF);
2041 SET_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +08002042 }
2043}
2044
2045/****************************************************************************
2046REMARKS:
2047Implements the IDIV instruction and side effects.
2048****************************************************************************/
2049void idiv_byte(u8 s)
2050{
2051 s32 dvd, div, mod;
2052
2053 dvd = (s16)M.x86.R_AX;
2054 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002055 x86emu_intr_raise(0);
2056 return;
Jason Jina63ce952007-07-06 08:34:56 +08002057 }
2058 div = dvd / (s8)s;
2059 mod = dvd % (s8)s;
2060 if (abs(div) > 0x7f) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002061 x86emu_intr_raise(0);
2062 return;
Jason Jina63ce952007-07-06 08:34:56 +08002063 }
2064 M.x86.R_AL = (s8) div;
2065 M.x86.R_AH = (s8) mod;
2066}
2067
2068/****************************************************************************
2069REMARKS:
2070Implements the IDIV instruction and side effects.
2071****************************************************************************/
2072void idiv_word(u16 s)
2073{
2074 s32 dvd, div, mod;
2075
2076 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2077 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002078 x86emu_intr_raise(0);
2079 return;
Jason Jina63ce952007-07-06 08:34:56 +08002080 }
2081 div = dvd / (s16)s;
2082 mod = dvd % (s16)s;
2083 if (abs(div) > 0x7fff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002084 x86emu_intr_raise(0);
2085 return;
Jason Jina63ce952007-07-06 08:34:56 +08002086 }
2087 CLEAR_FLAG(F_CF);
2088 CLEAR_FLAG(F_SF);
2089 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2090 set_parity_flag(mod);
2091
2092 M.x86.R_AX = (u16)div;
2093 M.x86.R_DX = (u16)mod;
2094}
2095
2096/****************************************************************************
2097REMARKS:
2098Implements the IDIV instruction and side effects.
2099****************************************************************************/
2100void idiv_long(u32 s)
2101{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002102#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08002103 s64 dvd, div, mod;
2104
2105 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2106 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002107 x86emu_intr_raise(0);
2108 return;
Jason Jina63ce952007-07-06 08:34:56 +08002109 }
2110 div = dvd / (s32)s;
2111 mod = dvd % (s32)s;
2112 if (abs(div) > 0x7fffffff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002113 x86emu_intr_raise(0);
2114 return;
Jason Jina63ce952007-07-06 08:34:56 +08002115 }
2116#else
2117 s32 div = 0, mod;
2118 s32 h_dvd = M.x86.R_EDX;
2119 u32 l_dvd = M.x86.R_EAX;
2120 u32 abs_s = s & 0x7FFFFFFF;
2121 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2122 u32 h_s = abs_s >> 1;
2123 u32 l_s = abs_s << 31;
2124 int counter = 31;
2125 int carry;
2126
2127 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002128 x86emu_intr_raise(0);
2129 return;
Jason Jina63ce952007-07-06 08:34:56 +08002130 }
2131 do {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002132 div <<= 1;
2133 carry = (l_dvd >= l_s) ? 0 : 1;
Jason Jina63ce952007-07-06 08:34:56 +08002134
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002135 if (abs_h_dvd < (h_s + carry)) {
2136 h_s >>= 1;
2137 l_s = abs_s << (--counter);
2138 continue;
2139 } else {
2140 abs_h_dvd -= (h_s + carry);
2141 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2142 : (l_dvd - l_s);
2143 h_s >>= 1;
2144 l_s = abs_s << (--counter);
2145 div |= 1;
2146 continue;
2147 }
Jason Jina63ce952007-07-06 08:34:56 +08002148
2149 } while (counter > -1);
2150 /* overflow */
2151 if (abs_h_dvd || (l_dvd > abs_s)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002152 x86emu_intr_raise(0);
2153 return;
Jason Jina63ce952007-07-06 08:34:56 +08002154 }
2155 /* sign */
2156 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2157 mod = l_dvd;
2158
2159#endif
2160 CLEAR_FLAG(F_CF);
2161 CLEAR_FLAG(F_AF);
2162 CLEAR_FLAG(F_SF);
2163 SET_FLAG(F_ZF);
2164 set_parity_flag(mod);
2165
2166 M.x86.R_EAX = (u32)div;
2167 M.x86.R_EDX = (u32)mod;
2168}
2169
2170/****************************************************************************
2171REMARKS:
2172Implements the DIV instruction and side effects.
2173****************************************************************************/
2174void div_byte(u8 s)
2175{
2176 u32 dvd, div, mod;
2177
2178 dvd = M.x86.R_AX;
2179 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002180 x86emu_intr_raise(0);
2181 return;
Jason Jina63ce952007-07-06 08:34:56 +08002182 }
2183 div = dvd / (u8)s;
2184 mod = dvd % (u8)s;
2185 if (abs(div) > 0xff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002186 x86emu_intr_raise(0);
2187 return;
Jason Jina63ce952007-07-06 08:34:56 +08002188 }
2189 M.x86.R_AL = (u8)div;
2190 M.x86.R_AH = (u8)mod;
2191}
2192
2193/****************************************************************************
2194REMARKS:
2195Implements the DIV instruction and side effects.
2196****************************************************************************/
2197void div_word(u16 s)
2198{
2199 u32 dvd, div, mod;
2200
2201 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2202 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002203 x86emu_intr_raise(0);
2204 return;
Jason Jina63ce952007-07-06 08:34:56 +08002205 }
2206 div = dvd / (u16)s;
2207 mod = dvd % (u16)s;
2208 if (abs(div) > 0xffff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002209 x86emu_intr_raise(0);
2210 return;
Jason Jina63ce952007-07-06 08:34:56 +08002211 }
2212 CLEAR_FLAG(F_CF);
2213 CLEAR_FLAG(F_SF);
2214 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2215 set_parity_flag(mod);
2216
2217 M.x86.R_AX = (u16)div;
2218 M.x86.R_DX = (u16)mod;
2219}
2220
2221/****************************************************************************
2222REMARKS:
2223Implements the DIV instruction and side effects.
2224****************************************************************************/
2225void div_long(u32 s)
2226{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002227#ifdef __HAS_LONG_LONG__
Jason Jina63ce952007-07-06 08:34:56 +08002228 u64 dvd, div, mod;
2229
2230 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2231 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002232 x86emu_intr_raise(0);
2233 return;
Jason Jina63ce952007-07-06 08:34:56 +08002234 }
2235 div = dvd / (u32)s;
2236 mod = dvd % (u32)s;
2237 if (abs(div) > 0xffffffff) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002238 x86emu_intr_raise(0);
2239 return;
Jason Jina63ce952007-07-06 08:34:56 +08002240 }
2241#else
2242 s32 div = 0, mod;
2243 s32 h_dvd = M.x86.R_EDX;
2244 u32 l_dvd = M.x86.R_EAX;
2245
2246 u32 h_s = s;
2247 u32 l_s = 0;
2248 int counter = 32;
2249 int carry;
2250
2251 if (s == 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002252 x86emu_intr_raise(0);
2253 return;
Jason Jina63ce952007-07-06 08:34:56 +08002254 }
2255 do {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002256 div <<= 1;
2257 carry = (l_dvd >= l_s) ? 0 : 1;
Jason Jina63ce952007-07-06 08:34:56 +08002258
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002259 if (h_dvd < (h_s + carry)) {
2260 h_s >>= 1;
2261 l_s = s << (--counter);
2262 continue;
2263 } else {
2264 h_dvd -= (h_s + carry);
2265 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2266 : (l_dvd - l_s);
2267 h_s >>= 1;
2268 l_s = s << (--counter);
2269 div |= 1;
2270 continue;
2271 }
Jason Jina63ce952007-07-06 08:34:56 +08002272
2273 } while (counter > -1);
2274 /* overflow */
2275 if (h_dvd || (l_dvd > s)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002276 x86emu_intr_raise(0);
2277 return;
Jason Jina63ce952007-07-06 08:34:56 +08002278 }
2279 mod = l_dvd;
2280#endif
2281 CLEAR_FLAG(F_CF);
2282 CLEAR_FLAG(F_AF);
2283 CLEAR_FLAG(F_SF);
2284 SET_FLAG(F_ZF);
2285 set_parity_flag(mod);
2286
2287 M.x86.R_EAX = (u32)div;
2288 M.x86.R_EDX = (u32)mod;
2289}
2290
2291/****************************************************************************
2292REMARKS:
2293Implements the IN string instruction and side effects.
2294****************************************************************************/
2295
2296static void single_in(int size)
2297{
2298 if(size == 1)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002299 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 +08002300 else if (size == 2)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002301 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 +08002302 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002303 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 +08002304}
2305
2306void ins(int size)
2307{
2308 int inc = size;
2309
2310 if (ACCESS_FLAG(F_DF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002311 inc = -size;
Jason Jina63ce952007-07-06 08:34:56 +08002312 }
2313 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002314 /* dont care whether REPE or REPNE */
2315 /* in until CX is ZERO. */
2316 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2317 M.x86.R_ECX : M.x86.R_CX);
Jason Jina63ce952007-07-06 08:34:56 +08002318
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002319 while (count--) {
2320 single_in(size);
2321 M.x86.R_DI += inc;
2322 }
2323 M.x86.R_CX = 0;
2324 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2325 M.x86.R_ECX = 0;
2326 }
2327 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002328 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002329 single_in(size);
2330 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002331 }
2332}
2333
2334/****************************************************************************
2335REMARKS:
2336Implements the OUT string instruction and side effects.
2337****************************************************************************/
2338
2339static void single_out(int size)
2340{
2341 if(size == 1)
2342 (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2343 else if (size == 2)
2344 (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2345 else
2346 (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2347}
2348
2349void outs(int size)
2350{
2351 int inc = size;
2352
2353 if (ACCESS_FLAG(F_DF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002354 inc = -size;
Jason Jina63ce952007-07-06 08:34:56 +08002355 }
2356 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002357 /* dont care whether REPE or REPNE */
2358 /* out until CX is ZERO. */
2359 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2360 M.x86.R_ECX : M.x86.R_CX);
2361 while (count--) {
2362 single_out(size);
2363 M.x86.R_SI += inc;
2364 }
2365 M.x86.R_CX = 0;
2366 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2367 M.x86.R_ECX = 0;
2368 }
2369 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002370 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002371 single_out(size);
2372 M.x86.R_SI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002373 }
2374}
2375
2376/****************************************************************************
2377PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002378addr - Address to fetch word from
Jason Jina63ce952007-07-06 08:34:56 +08002379
2380REMARKS:
2381Fetches a word from emulator memory using an absolute address.
2382****************************************************************************/
2383u16 mem_access_word(int addr)
2384{
2385DB( if (CHECK_MEM_ACCESS())
2386 x86emu_check_mem_access(addr);)
2387 return (*sys_rdw)(addr);
2388}
2389
2390/****************************************************************************
2391REMARKS:
2392Pushes a word onto the stack.
2393
2394NOTE: Do not inline this, as (*sys_wrX) is already inline!
2395****************************************************************************/
2396void push_word(u16 w)
2397{
2398DB( if (CHECK_SP_ACCESS())
2399 x86emu_check_sp_access();)
2400 M.x86.R_SP -= 2;
2401 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2402}
2403
2404/****************************************************************************
2405REMARKS:
2406Pushes a long onto the stack.
2407
2408NOTE: Do not inline this, as (*sys_wrX) is already inline!
2409****************************************************************************/
2410void push_long(u32 w)
2411{
2412DB( if (CHECK_SP_ACCESS())
2413 x86emu_check_sp_access();)
2414 M.x86.R_SP -= 4;
2415 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2416}
2417
2418/****************************************************************************
2419REMARKS:
2420Pops a word from the stack.
2421
2422NOTE: Do not inline this, as (*sys_rdX) is already inline!
2423****************************************************************************/
2424u16 pop_word(void)
2425{
2426 u16 res;
2427
2428DB( if (CHECK_SP_ACCESS())
2429 x86emu_check_sp_access();)
2430 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2431 M.x86.R_SP += 2;
2432 return res;
2433}
2434
2435/****************************************************************************
2436REMARKS:
2437Pops a long from the stack.
2438
2439NOTE: Do not inline this, as (*sys_rdX) is already inline!
2440****************************************************************************/
2441u32 pop_long(void)
2442{
2443 u32 res;
2444
2445DB( if (CHECK_SP_ACCESS())
2446 x86emu_check_sp_access();)
2447 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2448 M.x86.R_SP += 4;
2449 return res;
2450}
Jason Jin7ed5cd92007-08-08 08:33:11 +08002451
2452#endif