1/****************************************************************************
2*
3*						Realmode X86 Emulator Library
4*
5*            	Copyright (C) 1996-1999 SciTech Software, Inc.
6* 				     Copyright (C) David Mosberger-Tang
7* 					   Copyright (C) 1999 Egbert Eich
8*
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
17*  without specific, written prior permission.  The authors makes no
18*  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*
31* Language:		ANSI C
32* Environment:	Any
33* Developer:    Kendall Bennett
34*
35* Description:  This file contains the code to implement the primitive
36*				machine operations used by the emulation code in ops.c
37*
38* Carry Chain Calculation
39*
40* This represents a somewhat expensive calculation which is
41* apparently required to emulate the setting of the OF 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*
51* 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
60*
61* Construction of table for cout:
62*
63* ab
64* r  \  00   01   11  10
65* |------------------
66* 0  |   0    1    1   1
67* 1  |   0    0    1   0
68*
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*
78* 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
87*
88* Construction of table for cout:
89*
90* ab
91* r  \  00   01   11  10
92* |------------------
93* 0  |   0    1    0   0
94* 1  |   1    1    1   0
95*
96* By inspection, one gets:  bc = a'b +  r(a' + b)
97*
98****************************************************************************/
99
100#include <stdlib.h>
101
102#define	PRIM_OPS_NO_REDEFINE_ASM
103#include "x86emu/x86emui.h"
104
105/*------------------------- 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)
120#define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
121
122/*----------------------------- Implementation ----------------------------*/
123
124/****************************************************************************
125REMARKS:
126Implements the AAA instruction and side effects.
127****************************************************************************/
128u16 aaa_word(u16 d)
129{
130	u16	res;
131	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
132		d += 0x6;
133		d += 0x100;
134		SET_FLAG(F_AF);
135		SET_FLAG(F_CF);
136	} else {
137		CLEAR_FLAG(F_CF);
138		CLEAR_FLAG(F_AF);
139	}
140	res = (u16)(d & 0xFF0F);
141	CLEAR_FLAG(F_SF);
142	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
143	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
144	return res;
145}
146
147/****************************************************************************
148REMARKS:
149Implements the AAA instruction and side effects.
150****************************************************************************/
151u16 aas_word(u16 d)
152{
153	u16	res;
154	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
155		d -= 0x6;
156		d -= 0x100;
157		SET_FLAG(F_AF);
158		SET_FLAG(F_CF);
159	} else {
160		CLEAR_FLAG(F_CF);
161		CLEAR_FLAG(F_AF);
162	}
163	res = (u16)(d & 0xFF0F);
164	CLEAR_FLAG(F_SF);
165	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
166	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
167	return res;
168}
169
170/****************************************************************************
171REMARKS:
172Implements the AAD instruction and side effects.
173****************************************************************************/
174u16 aad_word(u16 d)
175{
176	u16 l;
177	u8 hb, lb;
178
179	hb = (u8)((d >> 8) & 0xff);
180	lb = (u8)((d & 0xff));
181	l = (u16)((lb + 10 * hb) & 0xFF);
182
183	CLEAR_FLAG(F_CF);
184	CLEAR_FLAG(F_AF);
185	CLEAR_FLAG(F_OF);
186	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
187	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
188	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
189	return l;
190}
191
192/****************************************************************************
193REMARKS:
194Implements the AAM instruction and side effects.
195****************************************************************************/
196u16 aam_word(u8 d)
197{
198    u16 h, l;
199
200	h = (u16)(d / 10);
201	l = (u16)(d % 10);
202	l |= (u16)(h << 8);
203
204	CLEAR_FLAG(F_CF);
205	CLEAR_FLAG(F_AF);
206	CLEAR_FLAG(F_OF);
207	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
208	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
209	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
210    return l;
211}
212
213/****************************************************************************
214REMARKS:
215Implements the ADC instruction and side effects.
216****************************************************************************/
217u8 adc_byte(u8 d, u8 s)
218{
219	register u32 res;   /* all operands in native machine order */
220	register u32 cc;
221
222	if (ACCESS_FLAG(F_CF))
223		res = 1 + d + s;
224	else
225		res = d + s;
226
227	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
228	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
229	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
230	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
231
232	/* calculate the carry chain  SEE NOTE AT TOP. */
233	cc = (s & d) | ((~res) & (s | d));
234	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
235	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
236	return (u8)res;
237}
238
239/****************************************************************************
240REMARKS:
241Implements the ADC instruction and side effects.
242****************************************************************************/
243u16 adc_word(u16 d, u16 s)
244{
245	register u32 res;   /* all operands in native machine order */
246	register u32 cc;
247
248	if (ACCESS_FLAG(F_CF))
249		res = 1 + d + s;
250	else
251		res = d + s;
252
253	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
254	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
255	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
256	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
257
258	/* calculate the carry chain  SEE NOTE AT TOP. */
259	cc = (s & d) | ((~res) & (s | d));
260	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
261	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
262	return (u16)res;
263}
264
265/****************************************************************************
266REMARKS:
267Implements the ADC instruction and side effects.
268****************************************************************************/
269u32 adc_long(u32 d, u32 s)
270{
271	register u32 lo;	/* all operands in native machine order */
272	register u32 hi;
273	register u32 res;
274	register u32 cc;
275
276	if (ACCESS_FLAG(F_CF)) {
277		lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
278		res = 1 + d + s;
279		}
280	else {
281		lo = (d & 0xFFFF) + (s & 0xFFFF);
282		res = d + s;
283		}
284	hi = (lo >> 16) + (d >> 16) + (s >> 16);
285
286	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
287	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
288	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
289	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
290
291	/* calculate the carry chain  SEE NOTE AT TOP. */
292	cc = (s & d) | ((~res) & (s | d));
293	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
294	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
295	return res;
296}
297
298/****************************************************************************
299REMARKS:
300Implements the ADD instruction and side effects.
301****************************************************************************/
302u8 add_byte(u8 d, u8 s)
303{
304	register u32 res;   /* all operands in native machine order */
305	register u32 cc;
306
307	res = d + s;
308	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
309	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
310	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
311	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
312
313	/* calculate the carry chain  SEE NOTE AT TOP. */
314	cc = (s & d) | ((~res) & (s | d));
315	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
316	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
317	return (u8)res;
318}
319
320/****************************************************************************
321REMARKS:
322Implements the ADD instruction and side effects.
323****************************************************************************/
324u16 add_word(u16 d, u16 s)
325{
326	register u32 res;   /* all operands in native machine order */
327	register u32 cc;
328
329	res = d + s;
330	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
331	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
332	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
333	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
334
335	/* calculate the carry chain  SEE NOTE AT TOP. */
336	cc = (s & d) | ((~res) & (s | d));
337	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
338	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
339	return (u16)res;
340}
341
342/****************************************************************************
343REMARKS:
344Implements the ADD instruction and side effects.
345****************************************************************************/
346u32 add_long(u32 d, u32 s)
347{
348	register u32 lo;	/* all operands in native machine order */
349	register u32 hi;
350	register u32 res;
351	register u32 cc;
352
353	lo = (d & 0xFFFF) + (s & 0xFFFF);
354	res = d + s;
355	hi = (lo >> 16) + (d >> 16) + (s >> 16);
356
357	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
358	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
359	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
360	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
361
362    /* calculate the carry chain  SEE NOTE AT TOP. */
363    cc = (s & d) | ((~res) & (s | d));
364	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
365	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
366
367    return res;
368}
369
370/****************************************************************************
371REMARKS:
372Implements the AND instruction and side effects.
373****************************************************************************/
374u8 and_byte(u8 d, u8 s)
375{
376	register u8 res;    /* all operands in native machine order */
377
378	res = d & s;
379
380	/* set the flags  */
381	CLEAR_FLAG(F_OF);
382	CLEAR_FLAG(F_CF);
383	CLEAR_FLAG(F_AF);
384	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
385	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
386	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
387	return res;
388}
389
390/****************************************************************************
391REMARKS:
392Implements the AND instruction and side effects.
393****************************************************************************/
394u16 and_word(u16 d, u16 s)
395{
396    register u16 res;   /* all operands in native machine order */
397
398    res = d & s;
399
400    /* set the flags  */
401	CLEAR_FLAG(F_OF);
402	CLEAR_FLAG(F_CF);
403	CLEAR_FLAG(F_AF);
404	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
405	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
406	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
407    return res;
408}
409
410/****************************************************************************
411REMARKS:
412Implements the AND instruction and side effects.
413****************************************************************************/
414u32 and_long(u32 d, u32 s)
415{
416	register u32 res;   /* all operands in native machine order */
417
418	res = d & s;
419
420	/* set the flags  */
421	CLEAR_FLAG(F_OF);
422	CLEAR_FLAG(F_CF);
423	CLEAR_FLAG(F_AF);
424	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
425	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
426	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
427	return res;
428}
429
430/****************************************************************************
431REMARKS:
432Implements the CMP instruction and side effects.
433****************************************************************************/
434u8 cmp_byte(u8 d, u8 s)
435{
436	register u32 res;   /* all operands in native machine order */
437	register u32 bc;
438
439	res = d - s;
440	CLEAR_FLAG(F_CF);
441	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
442	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
443	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
444
445	/* calculate the borrow chain.  See note at top */
446	bc = (res & (~d | s)) | (~d & s);
447	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
448	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
449	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
450	return d;
451}
452
453/****************************************************************************
454REMARKS:
455Implements the CMP instruction and side effects.
456****************************************************************************/
457u16 cmp_word(u16 d, u16 s)
458{
459	register u32 res;   /* all operands in native machine order */
460	register u32 bc;
461
462	res = d - s;
463	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
464	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
465	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
466
467	/* calculate the borrow chain.  See note at top */
468    bc = (res & (~d | s)) | (~d & s);
469	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
470	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
471	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
472	return d;
473}
474
475/****************************************************************************
476REMARKS:
477Implements the CMP instruction and side effects.
478****************************************************************************/
479u32 cmp_long(u32 d, u32 s)
480{
481	register u32 res;   /* all operands in native machine order */
482	register u32 bc;
483
484	res = d - s;
485	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
486	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
487	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
488
489	/* calculate the borrow chain.  See note at top */
490	bc = (res & (~d | s)) | (~d & s);
491	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
492	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
493	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
494	return d;
495}
496
497/****************************************************************************
498REMARKS:
499Implements the DAA instruction and side effects.
500****************************************************************************/
501u8 daa_byte(u8 d)
502{
503	u32 res = d;
504	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
505		res += 6;
506		SET_FLAG(F_AF);
507	}
508	if (res > 0x9F || ACCESS_FLAG(F_CF)) {
509		res += 0x60;
510		SET_FLAG(F_CF);
511	}
512	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
513	CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
514	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
515	return (u8)res;
516}
517
518/****************************************************************************
519REMARKS:
520Implements the DAS instruction and side effects.
521****************************************************************************/
522u8 das_byte(u8 d)
523{
524	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
525		d -= 6;
526		SET_FLAG(F_AF);
527	}
528	if (d > 0x9F || ACCESS_FLAG(F_CF)) {
529		d -= 0x60;
530		SET_FLAG(F_CF);
531	}
532	CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
533	CONDITIONAL_SET_FLAG(d == 0, F_ZF);
534	CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
535	return d;
536}
537
538/****************************************************************************
539REMARKS:
540Implements the DEC instruction and side effects.
541****************************************************************************/
542u8 dec_byte(u8 d)
543{
544    register u32 res;   /* all operands in native machine order */
545    register u32 bc;
546
547    res = d - 1;
548	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
549	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
550	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
551
552	/* calculate the borrow chain.  See note at top */
553	/* based on sub_byte, uses s==1.  */
554	bc = (res & (~d | 1)) | (~d & 1);
555	/* carry flag unchanged */
556	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
557	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
558	return (u8)res;
559}
560
561/****************************************************************************
562REMARKS:
563Implements the DEC instruction and side effects.
564****************************************************************************/
565u16 dec_word(u16 d)
566{
567    register u32 res;   /* all operands in native machine order */
568    register u32 bc;
569
570    res = d - 1;
571	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
572	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
573	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
574
575    /* calculate the borrow chain.  See note at top */
576    /* based on the sub_byte routine, with s==1 */
577    bc = (res & (~d | 1)) | (~d & 1);
578    /* carry flag unchanged */
579	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
580	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
581	return (u16)res;
582}
583
584/****************************************************************************
585REMARKS:
586Implements the DEC instruction and side effects.
587****************************************************************************/
588u32 dec_long(u32 d)
589{
590    register u32 res;   /* all operands in native machine order */
591    register u32 bc;
592
593    res = d - 1;
594
595	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
596	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
597	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
598
599    /* calculate the borrow chain.  See note at top */
600	bc = (res & (~d | 1)) | (~d & 1);
601	/* carry flag unchanged */
602	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
603	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
604	return res;
605}
606
607/****************************************************************************
608REMARKS:
609Implements the INC instruction and side effects.
610****************************************************************************/
611u8 inc_byte(u8 d)
612{
613	register u32 res;   /* all operands in native machine order */
614	register u32 cc;
615
616	res = d + 1;
617	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
618	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
619	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
620
621	/* calculate the carry chain  SEE NOTE AT TOP. */
622	cc = ((1 & d) | (~res)) & (1 | d);
623	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
624	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
625	return (u8)res;
626}
627
628/****************************************************************************
629REMARKS:
630Implements the INC instruction and side effects.
631****************************************************************************/
632u16 inc_word(u16 d)
633{
634	register u32 res;   /* all operands in native machine order */
635	register u32 cc;
636
637	res = d + 1;
638	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
639	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
640	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
641
642	/* calculate the carry chain  SEE NOTE AT TOP. */
643	cc = (1 & d) | ((~res) & (1 | d));
644	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
645	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
646	return (u16)res;
647}
648
649/****************************************************************************
650REMARKS:
651Implements the INC instruction and side effects.
652****************************************************************************/
653u32 inc_long(u32 d)
654{
655	register u32 res;   /* all operands in native machine order */
656	register u32 cc;
657
658	res = d + 1;
659	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
660	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
661	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
662
663	/* calculate the carry chain  SEE NOTE AT TOP. */
664	cc = (1 & d) | ((~res) & (1 | d));
665	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
666	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
667	return res;
668}
669
670/****************************************************************************
671REMARKS:
672Implements the OR instruction and side effects.
673****************************************************************************/
674u8 or_byte(u8 d, u8 s)
675{
676	register u8 res;    /* all operands in native machine order */
677
678	res = d | s;
679	CLEAR_FLAG(F_OF);
680	CLEAR_FLAG(F_CF);
681	CLEAR_FLAG(F_AF);
682	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
683	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
684	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
685	return res;
686}
687
688/****************************************************************************
689REMARKS:
690Implements the OR instruction and side effects.
691****************************************************************************/
692u16 or_word(u16 d, u16 s)
693{
694	register u16 res;   /* all operands in native machine order */
695
696	res = d | s;
697	/* set the carry flag to be bit 8 */
698	CLEAR_FLAG(F_OF);
699	CLEAR_FLAG(F_CF);
700	CLEAR_FLAG(F_AF);
701	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
702	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
703	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
704	return res;
705}
706
707/****************************************************************************
708REMARKS:
709Implements the OR instruction and side effects.
710****************************************************************************/
711u32 or_long(u32 d, u32 s)
712{
713	register u32 res;   /* all operands in native machine order */
714
715	res = d | s;
716
717	/* set the carry flag to be bit 8 */
718	CLEAR_FLAG(F_OF);
719	CLEAR_FLAG(F_CF);
720	CLEAR_FLAG(F_AF);
721	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
722	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
723	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
724	return res;
725}
726
727/****************************************************************************
728REMARKS:
729Implements the OR instruction and side effects.
730****************************************************************************/
731u8 neg_byte(u8 s)
732{
733    register u8 res;
734    register u8 bc;
735
736	CONDITIONAL_SET_FLAG(s != 0, F_CF);
737	res = (u8)-s;
738	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
739	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
740	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
741	/* calculate the borrow chain --- modified such that d=0.
742	   substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
743	   (the one used for sub) and simplifying, since ~d=0xff...,
744	   ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
745	   ~d&s == s.  So the simplified result is: */
746	bc = res | s;
747	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
748	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
749	return res;
750}
751
752/****************************************************************************
753REMARKS:
754Implements the OR instruction and side effects.
755****************************************************************************/
756u16 neg_word(u16 s)
757{
758	register u16 res;
759	register u16 bc;
760
761	CONDITIONAL_SET_FLAG(s != 0, F_CF);
762	res = (u16)-s;
763	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
764	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
765	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
766
767	/* calculate the borrow chain --- modified such that d=0.
768	   substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
769	   (the one used for sub) and simplifying, since ~d=0xff...,
770	   ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
771	   ~d&s == s.  So the simplified result is: */
772	bc = res | s;
773	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
774	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
775	return res;
776}
777
778/****************************************************************************
779REMARKS:
780Implements the OR instruction and side effects.
781****************************************************************************/
782u32 neg_long(u32 s)
783{
784	register u32 res;
785	register u32 bc;
786
787	CONDITIONAL_SET_FLAG(s != 0, F_CF);
788	res = (u32)-s;
789	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
790	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
791	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
792
793	/* calculate the borrow chain --- modified such that d=0.
794	   substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
795	   (the one used for sub) and simplifying, since ~d=0xff...,
796	   ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
797	   ~d&s == s.  So the simplified result is: */
798	bc = res | s;
799	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
800	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
801	return res;
802}
803
804/****************************************************************************
805REMARKS:
806Implements the NOT instruction and side effects.
807****************************************************************************/
808u8 not_byte(u8 s)
809{
810	return ~s;
811}
812
813/****************************************************************************
814REMARKS:
815Implements the NOT instruction and side effects.
816****************************************************************************/
817u16 not_word(u16 s)
818{
819	return ~s;
820}
821
822/****************************************************************************
823REMARKS:
824Implements the NOT instruction and side effects.
825****************************************************************************/
826u32 not_long(u32 s)
827{
828	return ~s;
829}
830
831/****************************************************************************
832REMARKS:
833Implements the RCL instruction and side effects.
834****************************************************************************/
835u8 rcl_byte(u8 d, u8 s)
836{
837    register unsigned int res, cnt, mask, cf;
838
839    /* s is the rotate distance.  It varies from 0 - 8. */
840	/* have
841
842       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
843
844       want to rotate through the carry by "s" bits.  We could
845       loop, but that's inefficient.  So the width is 9,
846       and we split into three parts:
847
848       The new carry flag   (was B_n)
849       the stuff in B_n-1 .. B_0
850       the stuff in B_7 .. B_n+1
851
852       The new rotate is done mod 9, and given this,
853       for a rotation of n bits (mod 9) the new carry flag is
854       then located n bits from the MSB.  The low part is
855       then shifted up cnt bits, and the high part is or'd
856       in.  Using CAPS for new values, and lowercase for the
857       original values, this can be expressed as:
858
859       IF n > 0
860       1) CF <-  b_(8-n)
861       2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
862       3) B_(n-1) <- cf
863       4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
864	 */
865	res = d;
866	if ((cnt = s % 9) != 0) {
867        /* extract the new CARRY FLAG. */
868        /* CF <-  b_(8-n)             */
869        cf = (d >> (8 - cnt)) & 0x1;
870
871        /* get the low stuff which rotated
872           into the range B_7 .. B_cnt */
873        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
874        /* note that the right hand side done by the mask */
875		res = (d << cnt) & 0xff;
876
877        /* now the high stuff which rotated around
878           into the positions B_cnt-2 .. B_0 */
879        /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
880        /* shift it downward, 7-(n-2) = 9-n positions.
881           and mask off the result before or'ing in.
882         */
883        mask = (1 << (cnt - 1)) - 1;
884        res |= (d >> (9 - cnt)) & mask;
885
886        /* if the carry flag was set, or it in.  */
887		if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
888            /*  B_(n-1) <- cf */
889            res |= 1 << (cnt - 1);
890        }
891        /* set the new carry flag, based on the variable "cf" */
892		CONDITIONAL_SET_FLAG(cf, F_CF);
893        /* OVERFLOW is set *IFF* cnt==1, then it is the
894           xor of CF and the most significant bit.  Blecck. */
895        /* parenthesized this expression since it appears to
896           be causing OF to be misset */
897        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
898							 F_OF);
899
900    }
901	return (u8)res;
902}
903
904/****************************************************************************
905REMARKS:
906Implements the RCL instruction and side effects.
907****************************************************************************/
908u16 rcl_word(u16 d, u8 s)
909{
910	register unsigned int res, cnt, mask, cf;
911
912	res = d;
913	if ((cnt = s % 17) != 0) {
914		cf = (d >> (16 - cnt)) & 0x1;
915		res = (d << cnt) & 0xffff;
916		mask = (1 << (cnt - 1)) - 1;
917		res |= (d >> (17 - cnt)) & mask;
918		if (ACCESS_FLAG(F_CF)) {
919			res |= 1 << (cnt - 1);
920		}
921		CONDITIONAL_SET_FLAG(cf, F_CF);
922		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
923							 F_OF);
924	}
925	return (u16)res;
926}
927
928/****************************************************************************
929REMARKS:
930Implements the RCL instruction and side effects.
931****************************************************************************/
932u32 rcl_long(u32 d, u8 s)
933{
934	register u32 res, cnt, mask, cf;
935
936	res = d;
937	if ((cnt = s % 33) != 0) {
938		cf = (d >> (32 - cnt)) & 0x1;
939		res = (d << cnt) & 0xffffffff;
940		mask = (1 << (cnt - 1)) - 1;
941		res |= (d >> (33 - cnt)) & mask;
942		if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
943			res |= 1 << (cnt - 1);
944		}
945		CONDITIONAL_SET_FLAG(cf, F_CF);
946		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
947							 F_OF);
948	}
949	return res;
950}
951
952/****************************************************************************
953REMARKS:
954Implements the RCR instruction and side effects.
955****************************************************************************/
956u8 rcr_byte(u8 d, u8 s)
957{
958	u32	res, cnt;
959	u32	mask, cf, ocf = 0;
960
961	/* rotate right through carry */
962    /*
963       s is the rotate distance.  It varies from 0 - 8.
964       d is the byte object rotated.
965
966       have
967
968       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
969
970       The new rotate is done mod 9, and given this,
971       for a rotation of n bits (mod 9) the new carry flag is
972       then located n bits from the LSB.  The low part is
973       then shifted up cnt bits, and the high part is or'd
974       in.  Using CAPS for new values, and lowercase for the
975       original values, this can be expressed as:
976
977       IF n > 0
978       1) CF <-  b_(n-1)
979       2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
980       3) B_(8-n) <- cf
981       4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
982	 */
983	res = d;
984	if ((cnt = s % 9) != 0) {
985        /* extract the new CARRY FLAG. */
986        /* CF <-  b_(n-1)              */
987        if (cnt == 1) {
988            cf = d & 0x1;
989            /* note hackery here.  Access_flag(..) evaluates to either
990               0 if flag not set
991               non-zero if flag is set.
992               doing access_flag(..) != 0 casts that into either
993			   0..1 in any representation of the flags register
994               (i.e. packed bit array or unpacked.)
995             */
996			ocf = ACCESS_FLAG(F_CF) != 0;
997        } else
998            cf = (d >> (cnt - 1)) & 0x1;
999
1000        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
1001        /* note that the right hand side done by the mask
1002           This is effectively done by shifting the
1003           object to the right.  The result must be masked,
1004           in case the object came in and was treated
1005           as a negative number.  Needed??? */
1006
1007        mask = (1 << (8 - cnt)) - 1;
1008        res = (d >> cnt) & mask;
1009
1010        /* now the high stuff which rotated around
1011           into the positions B_cnt-2 .. B_0 */
1012        /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
1013        /* shift it downward, 7-(n-2) = 9-n positions.
1014           and mask off the result before or'ing in.
1015         */
1016        res |= (d << (9 - cnt));
1017
1018        /* if the carry flag was set, or it in.  */
1019		if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1020            /*  B_(8-n) <- cf */
1021            res |= 1 << (8 - cnt);
1022        }
1023        /* set the new carry flag, based on the variable "cf" */
1024		CONDITIONAL_SET_FLAG(cf, F_CF);
1025        /* OVERFLOW is set *IFF* cnt==1, then it is the
1026           xor of CF and the most significant bit.  Blecck. */
1027        /* parenthesized... */
1028		if (cnt == 1) {
1029			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
1030								 F_OF);
1031		}
1032	}
1033	return (u8)res;
1034}
1035
1036/****************************************************************************
1037REMARKS:
1038Implements the RCR instruction and side effects.
1039****************************************************************************/
1040u16 rcr_word(u16 d, u8 s)
1041{
1042	u32 res, cnt;
1043	u32	mask, cf, ocf = 0;
1044
1045	/* rotate right through carry */
1046	res = d;
1047	if ((cnt = s % 17) != 0) {
1048		if (cnt == 1) {
1049			cf = d & 0x1;
1050			ocf = ACCESS_FLAG(F_CF) != 0;
1051		} else
1052			cf = (d >> (cnt - 1)) & 0x1;
1053		mask = (1 << (16 - cnt)) - 1;
1054		res = (d >> cnt) & mask;
1055		res |= (d << (17 - cnt));
1056		if (ACCESS_FLAG(F_CF)) {
1057			res |= 1 << (16 - cnt);
1058		}
1059		CONDITIONAL_SET_FLAG(cf, F_CF);
1060		if (cnt == 1) {
1061			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
1062								 F_OF);
1063		}
1064	}
1065	return (u16)res;
1066}
1067
1068/****************************************************************************
1069REMARKS:
1070Implements the RCR instruction and side effects.
1071****************************************************************************/
1072u32 rcr_long(u32 d, u8 s)
1073{
1074	u32 res, cnt;
1075	u32 mask, cf, ocf = 0;
1076
1077	/* rotate right through carry */
1078	res = d;
1079	if ((cnt = s % 33) != 0) {
1080		if (cnt == 1) {
1081			cf = d & 0x1;
1082			ocf = ACCESS_FLAG(F_CF) != 0;
1083		} else
1084			cf = (d >> (cnt - 1)) & 0x1;
1085		mask = (1 << (32 - cnt)) - 1;
1086		res = (d >> cnt) & mask;
1087		if (cnt != 1)
1088			res |= (d << (33 - cnt));
1089		if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1090			res |= 1 << (32 - cnt);
1091		}
1092		CONDITIONAL_SET_FLAG(cf, F_CF);
1093		if (cnt == 1) {
1094			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
1095								 F_OF);
1096		}
1097	}
1098	return res;
1099}
1100
1101/****************************************************************************
1102REMARKS:
1103Implements the ROL instruction and side effects.
1104****************************************************************************/
1105u8 rol_byte(u8 d, u8 s)
1106{
1107    register unsigned int res, cnt, mask;
1108
1109    /* rotate left */
1110    /*
1111       s is the rotate distance.  It varies from 0 - 8.
1112       d is the byte object rotated.
1113
1114       have
1115
1116       CF  B_7 ... B_0
1117
1118       The new rotate is done mod 8.
1119       Much simpler than the "rcl" or "rcr" operations.
1120
1121       IF n > 0
1122       1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
1123       2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
1124	 */
1125    res = d;
1126	if ((cnt = s % 8) != 0) {
1127		/* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1128		res = (d << cnt);
1129
1130		/* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1131		mask = (1 << cnt) - 1;
1132		res |= (d >> (8 - cnt)) & mask;
1133
1134		/* set the new carry flag, Note that it is the low order
1135		   bit of the result!!!                               */
1136		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1137		/* OVERFLOW is set *IFF* s==1, then it is the
1138		   xor of CF and the most significant bit.  Blecck. */
1139		CONDITIONAL_SET_FLAG(s == 1 &&
1140							 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1141							 F_OF);
1142	} if (s != 0) {
1143		/* set the new carry flag, Note that it is the low order
1144		   bit of the result!!!                               */
1145		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1146	}
1147	return (u8)res;
1148}
1149
1150/****************************************************************************
1151REMARKS:
1152Implements the ROL instruction and side effects.
1153****************************************************************************/
1154u16 rol_word(u16 d, u8 s)
1155{
1156    register unsigned int res, cnt, mask;
1157
1158	res = d;
1159	if ((cnt = s % 16) != 0) {
1160		res = (d << cnt);
1161		mask = (1 << cnt) - 1;
1162		res |= (d >> (16 - cnt)) & mask;
1163		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1164		CONDITIONAL_SET_FLAG(s == 1 &&
1165							 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1166							 F_OF);
1167	} if (s != 0) {
1168		/* set the new carry flag, Note that it is the low order
1169		   bit of the result!!!                               */
1170		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1171	}
1172	return (u16)res;
1173}
1174
1175/****************************************************************************
1176REMARKS:
1177Implements the ROL instruction and side effects.
1178****************************************************************************/
1179u32 rol_long(u32 d, u8 s)
1180{
1181    register u32 res, cnt, mask;
1182
1183	res = d;
1184	if ((cnt = s % 32) != 0) {
1185		res = (d << cnt);
1186		mask = (1 << cnt) - 1;
1187		res |= (d >> (32 - cnt)) & mask;
1188		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1189		CONDITIONAL_SET_FLAG(s == 1 &&
1190							 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1191							 F_OF);
1192	} if (s != 0) {
1193		/* set the new carry flag, Note that it is the low order
1194		   bit of the result!!!                               */
1195		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1196	}
1197	return res;
1198}
1199
1200/****************************************************************************
1201REMARKS:
1202Implements the ROR instruction and side effects.
1203****************************************************************************/
1204u8 ror_byte(u8 d, u8 s)
1205{
1206    register unsigned int res, cnt, mask;
1207
1208    /* rotate right */
1209    /*
1210       s is the rotate distance.  It varies from 0 - 8.
1211       d is the byte object rotated.
1212
1213       have
1214
1215       B_7 ... B_0
1216
1217       The rotate is done mod 8.
1218
1219       IF n > 0
1220       1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
1221       2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
1222	 */
1223	res = d;
1224	if ((cnt = s % 8) != 0) {           /* not a typo, do nada if cnt==0 */
1225        /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
1226        res = (d << (8 - cnt));
1227
1228        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
1229        mask = (1 << (8 - cnt)) - 1;
1230        res |= (d >> (cnt)) & mask;
1231
1232        /* set the new carry flag, Note that it is the low order
1233           bit of the result!!!                               */
1234		CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1235		/* OVERFLOW is set *IFF* s==1, then it is the
1236           xor of the two most significant bits.  Blecck. */
1237		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1238	} else if (s != 0) {
1239		/* set the new carry flag, Note that it is the low order
1240		   bit of the result!!!                               */
1241		CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1242	}
1243	return (u8)res;
1244}
1245
1246/****************************************************************************
1247REMARKS:
1248Implements the ROR instruction and side effects.
1249****************************************************************************/
1250u16 ror_word(u16 d, u8 s)
1251{
1252    register unsigned int res, cnt, mask;
1253
1254	res = d;
1255	if ((cnt = s % 16) != 0) {
1256		res = (d << (16 - cnt));
1257		mask = (1 << (16 - cnt)) - 1;
1258		res |= (d >> (cnt)) & mask;
1259		CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1260		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1261	} else if (s != 0) {
1262		/* set the new carry flag, Note that it is the low order
1263		   bit of the result!!!                               */
1264		CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1265	}
1266	return (u16)res;
1267}
1268
1269/****************************************************************************
1270REMARKS:
1271Implements the ROR instruction and side effects.
1272****************************************************************************/
1273u32 ror_long(u32 d, u8 s)
1274{
1275	register u32 res, cnt, mask;
1276
1277	res = d;
1278	if ((cnt = s % 32) != 0) {
1279		res = (d << (32 - cnt));
1280		mask = (1 << (32 - cnt)) - 1;
1281		res |= (d >> (cnt)) & mask;
1282		CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1283		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1284	} else if (s != 0) {
1285		/* set the new carry flag, Note that it is the low order
1286		   bit of the result!!!                               */
1287		CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1288	}
1289	return res;
1290}
1291
1292/****************************************************************************
1293REMARKS:
1294Implements the SHL instruction and side effects.
1295****************************************************************************/
1296u8 shl_byte(u8 d, u8 s)
1297{
1298	unsigned int cnt, res, cf;
1299
1300	if (s < 8) {
1301		cnt = s % 8;
1302
1303		/* last bit shifted out goes into carry flag */
1304		if (cnt > 0) {
1305			res = d << cnt;
1306			cf = d & (1 << (8 - cnt));
1307			CONDITIONAL_SET_FLAG(cf, F_CF);
1308			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1309			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1310			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1311		} else {
1312			res = (u8) d;
1313		}
1314
1315		if (cnt == 1) {
1316			/* Needs simplification. */
1317			CONDITIONAL_SET_FLAG(
1318									(((res & 0x80) == 0x80) ^
1319									 (ACCESS_FLAG(F_CF) != 0)),
1320			/* was (M.x86.R_FLG&F_CF)==F_CF)), */
1321									F_OF);
1322		} else {
1323			CLEAR_FLAG(F_OF);
1324		}
1325	} else {
1326		res = 0;
1327		CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1328		CLEAR_FLAG(F_OF);
1329		CLEAR_FLAG(F_SF);
1330		SET_FLAG(F_PF);
1331		SET_FLAG(F_ZF);
1332    }
1333	return (u8)res;
1334}
1335
1336/****************************************************************************
1337REMARKS:
1338Implements the SHL instruction and side effects.
1339****************************************************************************/
1340u16 shl_word(u16 d, u8 s)
1341{
1342    unsigned int cnt, res, cf;
1343
1344	if (s < 16) {
1345		cnt = s % 16;
1346		if (cnt > 0) {
1347			res = d << cnt;
1348			cf = d & (1 << (16 - cnt));
1349			CONDITIONAL_SET_FLAG(cf, F_CF);
1350			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1351			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1352			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1353		} else {
1354			res = (u16) d;
1355		}
1356
1357		if (cnt == 1) {
1358			CONDITIONAL_SET_FLAG(
1359									(((res & 0x8000) == 0x8000) ^
1360									 (ACCESS_FLAG(F_CF) != 0)),
1361									F_OF);
1362        } else {
1363			CLEAR_FLAG(F_OF);
1364        }
1365    } else {
1366		res = 0;
1367		CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1368		CLEAR_FLAG(F_OF);
1369		CLEAR_FLAG(F_SF);
1370		SET_FLAG(F_PF);
1371		SET_FLAG(F_ZF);
1372	}
1373	return (u16)res;
1374}
1375
1376/****************************************************************************
1377REMARKS:
1378Implements the SHL instruction and side effects.
1379****************************************************************************/
1380u32 shl_long(u32 d, u8 s)
1381{
1382	unsigned int cnt, res, cf;
1383
1384	if (s < 32) {
1385		cnt = s % 32;
1386		if (cnt > 0) {
1387			res = d << cnt;
1388			cf = d & (1 << (32 - cnt));
1389			CONDITIONAL_SET_FLAG(cf, F_CF);
1390			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1391			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1392			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1393		} else {
1394			res = d;
1395		}
1396		if (cnt == 1) {
1397			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1398								  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1399		} else {
1400			CLEAR_FLAG(F_OF);
1401		}
1402	} else {
1403		res = 0;
1404		CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1405		CLEAR_FLAG(F_OF);
1406		CLEAR_FLAG(F_SF);
1407		SET_FLAG(F_PF);
1408		SET_FLAG(F_ZF);
1409	}
1410	return res;
1411}
1412
1413/****************************************************************************
1414REMARKS:
1415Implements the SHR instruction and side effects.
1416****************************************************************************/
1417u8 shr_byte(u8 d, u8 s)
1418{
1419	unsigned int cnt, res, cf;
1420
1421	if (s < 8) {
1422		cnt = s % 8;
1423		if (cnt > 0) {
1424			cf = d & (1 << (cnt - 1));
1425			res = d >> cnt;
1426			CONDITIONAL_SET_FLAG(cf, F_CF);
1427			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1428			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1429			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1430		} else {
1431			res = (u8) d;
1432		}
1433
1434		if (cnt == 1) {
1435			CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1436		} else {
1437			CLEAR_FLAG(F_OF);
1438		}
1439	} else {
1440		res = 0;
1441		CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1442		CLEAR_FLAG(F_OF);
1443		CLEAR_FLAG(F_SF);
1444		SET_FLAG(F_PF);
1445		SET_FLAG(F_ZF);
1446	}
1447	return (u8)res;
1448}
1449
1450/****************************************************************************
1451REMARKS:
1452Implements the SHR instruction and side effects.
1453****************************************************************************/
1454u16 shr_word(u16 d, u8 s)
1455{
1456	unsigned int cnt, res, cf;
1457
1458	if (s < 16) {
1459		cnt = s % 16;
1460		if (cnt > 0) {
1461			cf = d & (1 << (cnt - 1));
1462			res = d >> cnt;
1463			CONDITIONAL_SET_FLAG(cf, F_CF);
1464			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1465			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1466			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1467		} else {
1468			res = d;
1469		}
1470
1471		if (cnt == 1) {
1472			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1473        } else {
1474			CLEAR_FLAG(F_OF);
1475        }
1476	} else {
1477		res = 0;
1478		CLEAR_FLAG(F_CF);
1479		CLEAR_FLAG(F_OF);
1480		SET_FLAG(F_ZF);
1481		CLEAR_FLAG(F_SF);
1482		CLEAR_FLAG(F_PF);
1483    }
1484	return (u16)res;
1485}
1486
1487/****************************************************************************
1488REMARKS:
1489Implements the SHR instruction and side effects.
1490****************************************************************************/
1491u32 shr_long(u32 d, u8 s)
1492{
1493	unsigned int cnt, res, cf;
1494
1495	if (s < 32) {
1496		cnt = s % 32;
1497		if (cnt > 0) {
1498			cf = d & (1 << (cnt - 1));
1499			res = d >> cnt;
1500			CONDITIONAL_SET_FLAG(cf, F_CF);
1501			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1502			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1503			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1504        } else {
1505            res = d;
1506        }
1507        if (cnt == 1) {
1508			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1509        } else {
1510			CLEAR_FLAG(F_OF);
1511        }
1512    } else {
1513        res = 0;
1514		CLEAR_FLAG(F_CF);
1515		CLEAR_FLAG(F_OF);
1516		SET_FLAG(F_ZF);
1517		CLEAR_FLAG(F_SF);
1518		CLEAR_FLAG(F_PF);
1519    }
1520    return res;
1521}
1522
1523/****************************************************************************
1524REMARKS:
1525Implements the SAR instruction and side effects.
1526****************************************************************************/
1527u8 sar_byte(u8 d, u8 s)
1528{
1529	unsigned int cnt, res, cf, mask, sf;
1530
1531	res = d;
1532	sf = d & 0x80;
1533    cnt = s % 8;
1534	if (cnt > 0 && cnt < 8) {
1535		mask = (1 << (8 - cnt)) - 1;
1536		cf = d & (1 << (cnt - 1));
1537		res = (d >> cnt) & mask;
1538		CONDITIONAL_SET_FLAG(cf, F_CF);
1539		if (sf) {
1540			res |= ~mask;
1541		}
1542		CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1543		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1544		CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1545    } else if (cnt >= 8) {
1546        if (sf) {
1547            res = 0xff;
1548			SET_FLAG(F_CF);
1549			CLEAR_FLAG(F_ZF);
1550			SET_FLAG(F_SF);
1551			SET_FLAG(F_PF);
1552		} else {
1553			res = 0;
1554			CLEAR_FLAG(F_CF);
1555			SET_FLAG(F_ZF);
1556			CLEAR_FLAG(F_SF);
1557			CLEAR_FLAG(F_PF);
1558		}
1559	}
1560	return (u8)res;
1561}
1562
1563/****************************************************************************
1564REMARKS:
1565Implements the SAR instruction and side effects.
1566****************************************************************************/
1567u16 sar_word(u16 d, u8 s)
1568{
1569    unsigned int cnt, res, cf, mask, sf;
1570
1571    sf = d & 0x8000;
1572    cnt = s % 16;
1573	res = d;
1574	if (cnt > 0 && cnt < 16) {
1575        mask = (1 << (16 - cnt)) - 1;
1576        cf = d & (1 << (cnt - 1));
1577        res = (d >> cnt) & mask;
1578		CONDITIONAL_SET_FLAG(cf, F_CF);
1579        if (sf) {
1580            res |= ~mask;
1581        }
1582		CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1583		CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1584		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1585    } else if (cnt >= 16) {
1586        if (sf) {
1587            res = 0xffff;
1588			SET_FLAG(F_CF);
1589			CLEAR_FLAG(F_ZF);
1590			SET_FLAG(F_SF);
1591			SET_FLAG(F_PF);
1592        } else {
1593            res = 0;
1594			CLEAR_FLAG(F_CF);
1595			SET_FLAG(F_ZF);
1596			CLEAR_FLAG(F_SF);
1597			CLEAR_FLAG(F_PF);
1598        }
1599    }
1600	return (u16)res;
1601}
1602
1603/****************************************************************************
1604REMARKS:
1605Implements the SAR instruction and side effects.
1606****************************************************************************/
1607u32 sar_long(u32 d, u8 s)
1608{
1609    u32 cnt, res, cf, mask, sf;
1610
1611    sf = d & 0x80000000;
1612    cnt = s % 32;
1613	res = d;
1614	if (cnt > 0 && cnt < 32) {
1615        mask = (1 << (32 - cnt)) - 1;
1616		cf = d & (1 << (cnt - 1));
1617        res = (d >> cnt) & mask;
1618		CONDITIONAL_SET_FLAG(cf, F_CF);
1619        if (sf) {
1620            res |= ~mask;
1621        }
1622		CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1623		CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1624		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1625    } else if (cnt >= 32) {
1626        if (sf) {
1627            res = 0xffffffff;
1628			SET_FLAG(F_CF);
1629			CLEAR_FLAG(F_ZF);
1630			SET_FLAG(F_SF);
1631			SET_FLAG(F_PF);
1632		} else {
1633			res = 0;
1634			CLEAR_FLAG(F_CF);
1635			SET_FLAG(F_ZF);
1636			CLEAR_FLAG(F_SF);
1637			CLEAR_FLAG(F_PF);
1638		}
1639	}
1640	return res;
1641}
1642
1643/****************************************************************************
1644REMARKS:
1645Implements the SHLD instruction and side effects.
1646****************************************************************************/
1647u16 shld_word (u16 d, u16 fill, u8 s)
1648{
1649	unsigned int cnt, res, cf;
1650
1651	if (s < 16) {
1652		cnt = s % 16;
1653		if (cnt > 0) {
1654			res = (d << cnt) | (fill >> (16-cnt));
1655			cf = d & (1 << (16 - cnt));
1656			CONDITIONAL_SET_FLAG(cf, F_CF);
1657			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1658			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1659			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1660		} else {
1661			res = d;
1662		}
1663		if (cnt == 1) {
1664			CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1665								  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1666		} else {
1667			CLEAR_FLAG(F_OF);
1668		}
1669	} else {
1670		res = 0;
1671		CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1672		CLEAR_FLAG(F_OF);
1673		CLEAR_FLAG(F_SF);
1674		SET_FLAG(F_PF);
1675		SET_FLAG(F_ZF);
1676	}
1677	return (u16)res;
1678}
1679
1680/****************************************************************************
1681REMARKS:
1682Implements the SHLD instruction and side effects.
1683****************************************************************************/
1684u32 shld_long (u32 d, u32 fill, u8 s)
1685{
1686	unsigned int cnt, res, cf;
1687
1688	if (s < 32) {
1689		cnt = s % 32;
1690		if (cnt > 0) {
1691			res = (d << cnt) | (fill >> (32-cnt));
1692			cf = d & (1 << (32 - cnt));
1693			CONDITIONAL_SET_FLAG(cf, F_CF);
1694			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1695			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1696			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1697		} else {
1698			res = d;
1699		}
1700		if (cnt == 1) {
1701			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1702								  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1703		} else {
1704			CLEAR_FLAG(F_OF);
1705		}
1706	} else {
1707		res = 0;
1708		CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1709		CLEAR_FLAG(F_OF);
1710		CLEAR_FLAG(F_SF);
1711		SET_FLAG(F_PF);
1712		SET_FLAG(F_ZF);
1713	}
1714	return res;
1715}
1716
1717/****************************************************************************
1718REMARKS:
1719Implements the SHRD instruction and side effects.
1720****************************************************************************/
1721u16 shrd_word (u16 d, u16 fill, u8 s)
1722{
1723	unsigned int cnt, res, cf;
1724
1725	if (s < 16) {
1726		cnt = s % 16;
1727		if (cnt > 0) {
1728			cf = d & (1 << (cnt - 1));
1729			res = (d >> cnt) | (fill << (16 - cnt));
1730			CONDITIONAL_SET_FLAG(cf, F_CF);
1731			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1732			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1733			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1734		} else {
1735			res = d;
1736		}
1737
1738		if (cnt == 1) {
1739			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1740        } else {
1741			CLEAR_FLAG(F_OF);
1742        }
1743	} else {
1744		res = 0;
1745		CLEAR_FLAG(F_CF);
1746		CLEAR_FLAG(F_OF);
1747		SET_FLAG(F_ZF);
1748		CLEAR_FLAG(F_SF);
1749		CLEAR_FLAG(F_PF);
1750    }
1751	return (u16)res;
1752}
1753
1754/****************************************************************************
1755REMARKS:
1756Implements the SHRD instruction and side effects.
1757****************************************************************************/
1758u32 shrd_long (u32 d, u32 fill, u8 s)
1759{
1760	unsigned int cnt, res, cf;
1761
1762	if (s < 32) {
1763		cnt = s % 32;
1764		if (cnt > 0) {
1765			cf = d & (1 << (cnt - 1));
1766			res = (d >> cnt) | (fill << (32 - cnt));
1767			CONDITIONAL_SET_FLAG(cf, F_CF);
1768			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1769			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1770			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1771		} else {
1772			res = d;
1773		}
1774		if (cnt == 1) {
1775			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1776        } else {
1777			CLEAR_FLAG(F_OF);
1778        }
1779	} else {
1780		res = 0;
1781		CLEAR_FLAG(F_CF);
1782		CLEAR_FLAG(F_OF);
1783		SET_FLAG(F_ZF);
1784		CLEAR_FLAG(F_SF);
1785		CLEAR_FLAG(F_PF);
1786    }
1787	return res;
1788}
1789
1790/****************************************************************************
1791REMARKS:
1792Implements the SBB instruction and side effects.
1793****************************************************************************/
1794u8 sbb_byte(u8 d, u8 s)
1795{
1796    register u32 res;   /* all operands in native machine order */
1797    register u32 bc;
1798
1799	if (ACCESS_FLAG(F_CF))
1800		res = d - s - 1;
1801	else
1802		res = d - s;
1803	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1804	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1805	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1806
1807	/* calculate the borrow chain.  See note at top */
1808	bc = (res & (~d | s)) | (~d & s);
1809	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1810	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1811	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1812	return (u8)res;
1813}
1814
1815/****************************************************************************
1816REMARKS:
1817Implements the SBB instruction and side effects.
1818****************************************************************************/
1819u16 sbb_word(u16 d, u16 s)
1820{
1821    register u32 res;   /* all operands in native machine order */
1822    register u32 bc;
1823
1824	if (ACCESS_FLAG(F_CF))
1825        res = d - s - 1;
1826    else
1827        res = d - s;
1828	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1829	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1830	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1831
1832	/* calculate the borrow chain.  See note at top */
1833	bc = (res & (~d | s)) | (~d & s);
1834	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1835	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1836	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1837	return (u16)res;
1838}
1839
1840/****************************************************************************
1841REMARKS:
1842Implements the SBB instruction and side effects.
1843****************************************************************************/
1844u32 sbb_long(u32 d, u32 s)
1845{
1846	register u32 res;   /* all operands in native machine order */
1847	register u32 bc;
1848
1849	if (ACCESS_FLAG(F_CF))
1850        res = d - s - 1;
1851    else
1852        res = d - s;
1853	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1854	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1855	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1856
1857	/* calculate the borrow chain.  See note at top */
1858	bc = (res & (~d | s)) | (~d & s);
1859	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1860	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1861	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1862	return res;
1863}
1864
1865/****************************************************************************
1866REMARKS:
1867Implements the SUB instruction and side effects.
1868****************************************************************************/
1869u8 sub_byte(u8 d, u8 s)
1870{
1871	register u32 res;   /* all operands in native machine order */
1872	register u32 bc;
1873
1874	res = d - s;
1875	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1876	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1877	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1878
1879	/* calculate the borrow chain.  See note at top */
1880	bc = (res & (~d | s)) | (~d & s);
1881	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1882	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1883	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1884	return (u8)res;
1885}
1886
1887/****************************************************************************
1888REMARKS:
1889Implements the SUB instruction and side effects.
1890****************************************************************************/
1891u16 sub_word(u16 d, u16 s)
1892{
1893    register u32 res;   /* all operands in native machine order */
1894    register u32 bc;
1895
1896    res = d - s;
1897	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1898	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1899	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1900
1901	/* calculate the borrow chain.  See note at top */
1902	bc = (res & (~d | s)) | (~d & s);
1903	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1904	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1905	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1906	return (u16)res;
1907}
1908
1909/****************************************************************************
1910REMARKS:
1911Implements the SUB instruction and side effects.
1912****************************************************************************/
1913u32 sub_long(u32 d, u32 s)
1914{
1915	register u32 res;   /* all operands in native machine order */
1916	register u32 bc;
1917
1918	res = d - s;
1919	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1920	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1921	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1922
1923	/* calculate the borrow chain.  See note at top */
1924	bc = (res & (~d | s)) | (~d & s);
1925	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1926	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1927	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1928	return res;
1929}
1930
1931/****************************************************************************
1932REMARKS:
1933Implements the TEST instruction and side effects.
1934****************************************************************************/
1935void test_byte(u8 d, u8 s)
1936{
1937    register u32 res;   /* all operands in native machine order */
1938
1939    res = d & s;
1940
1941	CLEAR_FLAG(F_OF);
1942	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1943	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1944	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1945    /* AF == dont care */
1946	CLEAR_FLAG(F_CF);
1947}
1948
1949/****************************************************************************
1950REMARKS:
1951Implements the TEST instruction and side effects.
1952****************************************************************************/
1953void test_word(u16 d, u16 s)
1954{
1955	register u32 res;   /* all operands in native machine order */
1956
1957	res = d & s;
1958
1959	CLEAR_FLAG(F_OF);
1960	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1961	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1962	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1963	/* AF == dont care */
1964	CLEAR_FLAG(F_CF);
1965}
1966
1967/****************************************************************************
1968REMARKS:
1969Implements the TEST instruction and side effects.
1970****************************************************************************/
1971void test_long(u32 d, u32 s)
1972{
1973	register u32 res;   /* all operands in native machine order */
1974
1975	res = d & s;
1976
1977	CLEAR_FLAG(F_OF);
1978	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1979	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1980	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1981	/* AF == dont care */
1982	CLEAR_FLAG(F_CF);
1983}
1984
1985/****************************************************************************
1986REMARKS:
1987Implements the XOR instruction and side effects.
1988****************************************************************************/
1989u8 xor_byte(u8 d, u8 s)
1990{
1991	register u8 res;    /* all operands in native machine order */
1992
1993	res = d ^ s;
1994	CLEAR_FLAG(F_OF);
1995	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1996	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1997	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
1998	CLEAR_FLAG(F_CF);
1999	CLEAR_FLAG(F_AF);
2000	return res;
2001}
2002
2003/****************************************************************************
2004REMARKS:
2005Implements the XOR instruction and side effects.
2006****************************************************************************/
2007u16 xor_word(u16 d, u16 s)
2008{
2009	register u16 res;   /* all operands in native machine order */
2010
2011	res = d ^ s;
2012	CLEAR_FLAG(F_OF);
2013	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2014	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2015	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2016	CLEAR_FLAG(F_CF);
2017	CLEAR_FLAG(F_AF);
2018	return res;
2019}
2020
2021/****************************************************************************
2022REMARKS:
2023Implements the XOR instruction and side effects.
2024****************************************************************************/
2025u32 xor_long(u32 d, u32 s)
2026{
2027	register u32 res;   /* all operands in native machine order */
2028
2029	res = d ^ s;
2030	CLEAR_FLAG(F_OF);
2031	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2032	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2033	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2034	CLEAR_FLAG(F_CF);
2035	CLEAR_FLAG(F_AF);
2036	return res;
2037}
2038
2039/****************************************************************************
2040REMARKS:
2041Implements the IMUL instruction and side effects.
2042****************************************************************************/
2043void imul_byte(u8 s)
2044{
2045	s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
2046
2047	M.x86.R_AX = res;
2048	if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2049		((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2050		CLEAR_FLAG(F_CF);
2051		CLEAR_FLAG(F_OF);
2052	} else {
2053		SET_FLAG(F_CF);
2054		SET_FLAG(F_OF);
2055	}
2056}
2057
2058/****************************************************************************
2059REMARKS:
2060Implements the IMUL instruction and side effects.
2061****************************************************************************/
2062void imul_word(u16 s)
2063{
2064	s32 res = (s16)M.x86.R_AX * (s16)s;
2065
2066	M.x86.R_AX = (u16)res;
2067	M.x86.R_DX = (u16)(res >> 16);
2068	if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
2069		((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
2070		CLEAR_FLAG(F_CF);
2071		CLEAR_FLAG(F_OF);
2072	} else {
2073		SET_FLAG(F_CF);
2074		SET_FLAG(F_OF);
2075	}
2076}
2077
2078/****************************************************************************
2079REMARKS:
2080Implements the IMUL instruction and side effects.
2081****************************************************************************/
2082void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2083{
2084#ifdef	__HAS_LONG_LONG__
2085	s64 res = (s64)(s32)d * (s32)s;
2086
2087	*res_lo = (u32)res;
2088	*res_hi = (u32)(res >> 32);
2089#else
2090	u32	d_lo,d_hi,d_sign;
2091	u32	s_lo,s_hi,s_sign;
2092	u32	rlo_lo,rlo_hi,rhi_lo;
2093
2094	if ((d_sign = d & 0x80000000) != 0)
2095		d = -d;
2096	d_lo = d & 0xFFFF;
2097	d_hi = d >> 16;
2098	if ((s_sign = s & 0x80000000) != 0)
2099		s = -s;
2100	s_lo = s & 0xFFFF;
2101	s_hi = s >> 16;
2102	rlo_lo = d_lo * s_lo;
2103	rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2104	rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2105	*res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2106	*res_hi = rhi_lo;
2107	if (d_sign != s_sign) {
2108		d = ~*res_lo;
2109		s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2110		*res_lo = ~*res_lo+1;
2111		*res_hi = ~*res_hi+(s >> 16);
2112		}
2113#endif
2114}
2115
2116/****************************************************************************
2117REMARKS:
2118Implements the IMUL instruction and side effects.
2119****************************************************************************/
2120void imul_long(u32 s)
2121{
2122	imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
2123	if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
2124		((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
2125		CLEAR_FLAG(F_CF);
2126		CLEAR_FLAG(F_OF);
2127	} else {
2128		SET_FLAG(F_CF);
2129		SET_FLAG(F_OF);
2130	}
2131}
2132
2133/****************************************************************************
2134REMARKS:
2135Implements the MUL instruction and side effects.
2136****************************************************************************/
2137void mul_byte(u8 s)
2138{
2139	u16 res = (u16)(M.x86.R_AL * s);
2140
2141	M.x86.R_AX = res;
2142	if (M.x86.R_AH == 0) {
2143		CLEAR_FLAG(F_CF);
2144		CLEAR_FLAG(F_OF);
2145	} else {
2146		SET_FLAG(F_CF);
2147		SET_FLAG(F_OF);
2148	}
2149}
2150
2151/****************************************************************************
2152REMARKS:
2153Implements the MUL instruction and side effects.
2154****************************************************************************/
2155void mul_word(u16 s)
2156{
2157	u32 res = M.x86.R_AX * s;
2158
2159	M.x86.R_AX = (u16)res;
2160	M.x86.R_DX = (u16)(res >> 16);
2161	if (M.x86.R_DX == 0) {
2162		CLEAR_FLAG(F_CF);
2163		CLEAR_FLAG(F_OF);
2164    } else {
2165		SET_FLAG(F_CF);
2166		SET_FLAG(F_OF);
2167    }
2168}
2169
2170/****************************************************************************
2171REMARKS:
2172Implements the MUL instruction and side effects.
2173****************************************************************************/
2174void mul_long(u32 s)
2175{
2176#ifdef	__HAS_LONG_LONG__
2177	u64 res = (u64)M.x86.R_EAX * s;
2178
2179	M.x86.R_EAX = (u32)res;
2180	M.x86.R_EDX = (u32)(res >> 32);
2181#else
2182	u32	a,a_lo,a_hi;
2183	u32	s_lo,s_hi;
2184	u32	rlo_lo,rlo_hi,rhi_lo;
2185
2186	a = M.x86.R_EAX;
2187	a_lo = a & 0xFFFF;
2188	a_hi = a >> 16;
2189	s_lo = s & 0xFFFF;
2190	s_hi = s >> 16;
2191	rlo_lo = a_lo * s_lo;
2192	rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2193	rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2194	M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2195	M.x86.R_EDX = rhi_lo;
2196#endif
2197
2198	if (M.x86.R_EDX == 0) {
2199		CLEAR_FLAG(F_CF);
2200		CLEAR_FLAG(F_OF);
2201	} else {
2202		SET_FLAG(F_CF);
2203		SET_FLAG(F_OF);
2204    }
2205}
2206
2207/****************************************************************************
2208REMARKS:
2209Implements the IDIV instruction and side effects.
2210****************************************************************************/
2211void idiv_byte(u8 s)
2212{
2213    s32 dvd, div, mod;
2214
2215	dvd = (s16)M.x86.R_AX;
2216	if (s == 0) {
2217		x86emu_intr_raise(0);
2218        return;
2219	}
2220	div = dvd / (s8)s;
2221	mod = dvd % (s8)s;
2222	if (abs(div) > 0x7f) {
2223		x86emu_intr_raise(0);
2224		return;
2225	}
2226	M.x86.R_AL = (s8) div;
2227	M.x86.R_AH = (s8) mod;
2228}
2229
2230/****************************************************************************
2231REMARKS:
2232Implements the IDIV instruction and side effects.
2233****************************************************************************/
2234void idiv_word(u16 s)
2235{
2236	s32 dvd, div, mod;
2237
2238	dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2239	if (s == 0) {
2240		x86emu_intr_raise(0);
2241		return;
2242	}
2243	div = dvd / (s16)s;
2244	mod = dvd % (s16)s;
2245	if (abs(div) > 0x7fff) {
2246		x86emu_intr_raise(0);
2247		return;
2248	}
2249	CLEAR_FLAG(F_CF);
2250	CLEAR_FLAG(F_SF);
2251	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2252	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2253
2254	M.x86.R_AX = (u16)div;
2255	M.x86.R_DX = (u16)mod;
2256}
2257
2258/****************************************************************************
2259REMARKS:
2260Implements the IDIV instruction and side effects.
2261****************************************************************************/
2262void idiv_long(u32 s)
2263{
2264#ifdef	__HAS_LONG_LONG__
2265	s64 dvd, div, mod;
2266
2267	dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2268	if (s == 0) {
2269		x86emu_intr_raise(0);
2270		return;
2271	}
2272	div = dvd / (s32)s;
2273	mod = dvd % (s32)s;
2274	if (abs(div) > 0x7fffffff) {
2275		x86emu_intr_raise(0);
2276		return;
2277	}
2278#else
2279	s32 div = 0, mod;
2280	s32 h_dvd = M.x86.R_EDX;
2281	u32 l_dvd = M.x86.R_EAX;
2282	u32 abs_s = s & 0x7FFFFFFF;
2283	u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2284	u32 h_s = abs_s >> 1;
2285	u32 l_s = abs_s << 31;
2286	int counter = 31;
2287	int carry;
2288
2289	if (s == 0) {
2290		x86emu_intr_raise(0);
2291		return;
2292	}
2293	do {
2294		div <<= 1;
2295		carry = (l_dvd >= l_s) ? 0 : 1;
2296
2297		if (abs_h_dvd < (h_s + carry)) {
2298			h_s >>= 1;
2299			l_s = abs_s << (--counter);
2300			continue;
2301		} else {
2302			abs_h_dvd -= (h_s + carry);
2303			l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2304				: (l_dvd - l_s);
2305			h_s >>= 1;
2306			l_s = abs_s << (--counter);
2307			div |= 1;
2308			continue;
2309		}
2310
2311	} while (counter > -1);
2312	/* overflow */
2313	if (abs_h_dvd || (l_dvd > abs_s)) {
2314		x86emu_intr_raise(0);
2315		return;
2316	}
2317	/* sign */
2318	div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2319	mod = l_dvd;
2320
2321#endif
2322	CLEAR_FLAG(F_CF);
2323	CLEAR_FLAG(F_AF);
2324	CLEAR_FLAG(F_SF);
2325	SET_FLAG(F_ZF);
2326	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2327
2328	M.x86.R_EAX = (u32)div;
2329	M.x86.R_EDX = (u32)mod;
2330}
2331
2332/****************************************************************************
2333REMARKS:
2334Implements the DIV instruction and side effects.
2335****************************************************************************/
2336void div_byte(u8 s)
2337{
2338	u32 dvd, div, mod;
2339
2340	dvd = M.x86.R_AX;
2341    if (s == 0) {
2342		x86emu_intr_raise(0);
2343        return;
2344    }
2345	div = dvd / (u8)s;
2346	mod = dvd % (u8)s;
2347	if (abs(div) > 0xff) {
2348		x86emu_intr_raise(0);
2349        return;
2350	}
2351	M.x86.R_AL = (u8)div;
2352	M.x86.R_AH = (u8)mod;
2353}
2354
2355/****************************************************************************
2356REMARKS:
2357Implements the DIV instruction and side effects.
2358****************************************************************************/
2359void div_word(u16 s)
2360{
2361	u32 dvd, div, mod;
2362
2363	dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2364	if (s == 0) {
2365		x86emu_intr_raise(0);
2366        return;
2367    }
2368	div = dvd / (u16)s;
2369	mod = dvd % (u16)s;
2370	if (abs(div) > 0xffff) {
2371		x86emu_intr_raise(0);
2372		return;
2373	}
2374	CLEAR_FLAG(F_CF);
2375	CLEAR_FLAG(F_SF);
2376	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2377	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2378
2379	M.x86.R_AX = (u16)div;
2380	M.x86.R_DX = (u16)mod;
2381}
2382
2383/****************************************************************************
2384REMARKS:
2385Implements the DIV instruction and side effects.
2386****************************************************************************/
2387void div_long(u32 s)
2388{
2389#ifdef	__HAS_LONG_LONG__
2390	u64 dvd, div, mod;
2391
2392	dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2393	if (s == 0) {
2394		x86emu_intr_raise(0);
2395		return;
2396	}
2397	div = dvd / (u32)s;
2398	mod = dvd % (u32)s;
2399	if (abs(div) > 0xffffffff) {
2400		x86emu_intr_raise(0);
2401		return;
2402	}
2403#else
2404	s32 div = 0, mod;
2405	s32 h_dvd = M.x86.R_EDX;
2406	u32 l_dvd = M.x86.R_EAX;
2407
2408	u32 h_s = s;
2409	u32 l_s = 0;
2410	int counter = 32;
2411	int carry;
2412
2413	if (s == 0) {
2414		x86emu_intr_raise(0);
2415		return;
2416	}
2417	do {
2418		div <<= 1;
2419		carry = (l_dvd >= l_s) ? 0 : 1;
2420
2421		if (h_dvd < (h_s + carry)) {
2422			h_s >>= 1;
2423			l_s = s << (--counter);
2424			continue;
2425		} else {
2426			h_dvd -= (h_s + carry);
2427			l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2428				: (l_dvd - l_s);
2429			h_s >>= 1;
2430			l_s = s << (--counter);
2431			div |= 1;
2432			continue;
2433		}
2434
2435	} while (counter > -1);
2436	/* overflow */
2437	if (h_dvd || (l_dvd > s)) {
2438		x86emu_intr_raise(0);
2439		return;
2440	}
2441	mod = l_dvd;
2442#endif
2443	CLEAR_FLAG(F_CF);
2444	CLEAR_FLAG(F_AF);
2445	CLEAR_FLAG(F_SF);
2446	SET_FLAG(F_ZF);
2447	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2448
2449	M.x86.R_EAX = (u32)div;
2450	M.x86.R_EDX = (u32)mod;
2451}
2452
2453/****************************************************************************
2454REMARKS:
2455Implements the IN string instruction and side effects.
2456****************************************************************************/
2457void ins(int size)
2458{
2459	int inc = size;
2460
2461	if (ACCESS_FLAG(F_DF)) {
2462		inc = -size;
2463	}
2464	if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2465        /* dont care whether REPE or REPNE */
2466        /* in until CX is ZERO. */
2467		u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2468					 M.x86.R_ECX : M.x86.R_CX);
2469        switch (size) {
2470          case 1:
2471            while (count--) {
2472				store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2473									(*sys_inb)(M.x86.R_DX));
2474				M.x86.R_DI += inc;
2475            }
2476            break;
2477
2478          case 2:
2479            while (count--) {
2480				store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2481									(*sys_inw)(M.x86.R_DX));
2482				M.x86.R_DI += inc;
2483            }
2484            break;
2485          case 4:
2486            while (count--) {
2487				store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2488									(*sys_inl)(M.x86.R_DX));
2489				M.x86.R_DI += inc;
2490                break;
2491            }
2492        }
2493		M.x86.R_CX = 0;
2494		if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2495			M.x86.R_ECX = 0;
2496        }
2497		M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2498    } else {
2499        switch (size) {
2500          case 1:
2501			store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2502								(*sys_inb)(M.x86.R_DX));
2503            break;
2504          case 2:
2505			store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2506								(*sys_inw)(M.x86.R_DX));
2507            break;
2508          case 4:
2509			store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2510								(*sys_inl)(M.x86.R_DX));
2511            break;
2512        }
2513		M.x86.R_DI += inc;
2514    }
2515}
2516
2517/****************************************************************************
2518REMARKS:
2519Implements the OUT string instruction and side effects.
2520****************************************************************************/
2521void outs(int size)
2522{
2523    int inc = size;
2524
2525	if (ACCESS_FLAG(F_DF)) {
2526        inc = -size;
2527    }
2528	if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2529        /* dont care whether REPE or REPNE */
2530        /* out until CX is ZERO. */
2531		u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2532					 M.x86.R_ECX : M.x86.R_CX);
2533        switch (size) {
2534          case 1:
2535            while (count--) {
2536				(*sys_outb)(M.x86.R_DX,
2537						 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2538				M.x86.R_SI += inc;
2539            }
2540            break;
2541
2542          case 2:
2543            while (count--) {
2544				(*sys_outw)(M.x86.R_DX,
2545						 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2546				M.x86.R_SI += inc;
2547            }
2548            break;
2549          case 4:
2550            while (count--) {
2551				(*sys_outl)(M.x86.R_DX,
2552						 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2553				M.x86.R_SI += inc;
2554                break;
2555            }
2556        }
2557		M.x86.R_CX = 0;
2558		if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2559			M.x86.R_ECX = 0;
2560        }
2561		M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2562    } else {
2563        switch (size) {
2564          case 1:
2565			(*sys_outb)(M.x86.R_DX,
2566					 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2567            break;
2568          case 2:
2569			(*sys_outw)(M.x86.R_DX,
2570					 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2571            break;
2572          case 4:
2573			(*sys_outl)(M.x86.R_DX,
2574					 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2575            break;
2576        }
2577		M.x86.R_SI += inc;
2578    }
2579}
2580
2581/****************************************************************************
2582PARAMETERS:
2583addr	- Address to fetch word from
2584
2585REMARKS:
2586Fetches a word from emulator memory using an absolute address.
2587****************************************************************************/
2588u16 mem_access_word(int addr)
2589{
2590DB(	if (CHECK_MEM_ACCESS())
2591	  x86emu_check_mem_access(addr);)
2592	return (*sys_rdw)(addr);
2593}
2594
2595/****************************************************************************
2596REMARKS:
2597Pushes a word onto the stack.
2598
2599NOTE: Do not inline this, as (*sys_wrX) is already inline!
2600****************************************************************************/
2601void push_word(u16 w)
2602{
2603DB(	if (CHECK_SP_ACCESS())
2604	  x86emu_check_sp_access();)
2605	M.x86.R_SP -= 2;
2606	(*sys_wrw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2607}
2608
2609/****************************************************************************
2610REMARKS:
2611Pushes a long onto the stack.
2612
2613NOTE: Do not inline this, as (*sys_wrX) is already inline!
2614****************************************************************************/
2615void push_long(u32 w)
2616{
2617DB(	if (CHECK_SP_ACCESS())
2618	  x86emu_check_sp_access();)
2619	M.x86.R_SP -= 4;
2620	(*sys_wrl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2621}
2622
2623/****************************************************************************
2624REMARKS:
2625Pops a word from the stack.
2626
2627NOTE: Do not inline this, as (*sys_rdX) is already inline!
2628****************************************************************************/
2629u16 pop_word(void)
2630{
2631	register u16 res;
2632
2633DB(	if (CHECK_SP_ACCESS())
2634	  x86emu_check_sp_access();)
2635	res = (*sys_rdw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2636	M.x86.R_SP += 2;
2637	return res;
2638}
2639
2640/****************************************************************************
2641REMARKS:
2642Pops a long from the stack.
2643
2644NOTE: Do not inline this, as (*sys_rdX) is already inline!
2645****************************************************************************/
2646u32 pop_long(void)
2647{
2648    register u32 res;
2649
2650DB(	if (CHECK_SP_ACCESS())
2651	  x86emu_check_sp_access();)
2652	res = (*sys_rdl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2653	M.x86.R_SP += 4;
2654    return res;
2655}
2656
2657