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