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